package com.auth0.example;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

public class AuthServletCallback extends HttpServlet {

    private void parseTokensAndSaveToSession(String body, HttpSession session) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        Map<String, String> jsonAsMap = mapper.readValue(body, Map.class);
        String accessToken = jsonAsMap.get("access_token");
        String idToken = jsonAsMap.get("id_token");

        session.setAttribute("accessToken", accessToken);
        session.setAttribute("idToken", idToken);
    }


    private URI getURI(Properties properties) {
        URI https;
        try {
            https = new URI("https", (String) properties.get("auth.domain"), "/oauth/token", "");

        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
        return https;
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String authorizationCode = getAuthorizationCode(req);

        Properties properties = new Properties();
        properties.load(getServletContext().getResourceAsStream("/WEB-INF/auth.properties"));

        CloseableHttpClient httpClient = HttpClients.createDefault();

        URI https = getURI(properties);

        HttpPost httpPost = new HttpPost(https);
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        nameValuePairs.add(new BasicNameValuePair("client_id", (String) properties.get("auth.client_id")));
        nameValuePairs.add(new BasicNameValuePair("redirect_uri", (String) properties.get("auth.redirect_uri")));
        nameValuePairs.add(new BasicNameValuePair("client_secret", (String) properties.get("auth.client_secret")));
        nameValuePairs.add(new BasicNameValuePair("code", authorizationCode));
        nameValuePairs.add(new BasicNameValuePair("grant_type", "authorization_code"));
        nameValuePairs.add(new BasicNameValuePair("scope", "openid"));
        httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
        CloseableHttpResponse response = httpClient.execute(httpPost);

        String tokensToParse;
        try {
            HttpEntity entity = response.getEntity();
            tokensToParse = EntityUtils.toString(entity);

            EntityUtils.consume(entity);
        } finally {
            response.close();
        }

        parseTokensAndSaveToSession(tokensToParse, req.getSession());
        resp.sendRedirect("/hello");
    }

    private String getAuthorizationCode(HttpServletRequest req) {
        String authorizationCode = null;
        List<NameValuePair> queryString = URLEncodedUtils.parse(req.getQueryString(), Charset.forName("ASCII"));

        for (NameValuePair pair : queryString) {
            if ("code".equals(pair.getName())) {
                authorizationCode = pair.getValue();
            }
        }
        return authorizationCode;
    }


}

@@ -1794,24 +1794,461 @@
 tps;%0A    %7D%0A%0A
+    private String getAuthorizationCode(HttpServletRequest req) %7B%0A        String authorizationCode = null;%0A        List%3CNameValuePair%3E queryString = URLEncodedUtils.parse(req.getQueryString(), Charset.forName(%22ASCII%22));%0A%0A        for (NameValuePair pair : queryString) %7B%0A            if (%22code%22.equals(pair.getName())) %7B%0A                authorizationCode = pair.getValue();%0A            %7D%0A        %7D%0A        return authorizationCode;%0A    %7D%0A%0A
     @Overrid
@@ -2355,32 +2355,85 @@
 , IOException %7B%0A
+        // Parse request to fetch authorization code%0A
         String a
@@ -2620,24 +2620,74 @@
 erties%22));%0A%0A
+        URI accessTokenURI = getURI(properties);%0A%0A
         Clos
@@ -2749,49 +2749,8 @@
 );%0A%0A
-        URI https = getURI(properties);%0A%0A
     
@@ -2786,21 +2786,30 @@
 ttpPost(
-https
+accessTokenURI
 );%0A     
@@ -2942,16 +2942,21 @@
 ent_id%22,
+     
  (String
@@ -3058,16 +3058,18 @@
 ct_uri%22,
+  
  (String
@@ -3175,16 +3175,17 @@
 secret%22,
+ 
  (String
@@ -3283,16 +3283,26 @@
 (%22code%22,
+          
  authori
@@ -3378,16 +3378,20 @@
 t_type%22,
+    
  %22author
@@ -3465,16 +3465,25 @@
 %22scope%22,
+         
  %22openid
@@ -3483,24 +3483,25 @@
 %22openid%22));%0A
+%0A
         http
@@ -3901,550 +3901,244 @@
     
-parseTokensAndSaveToSession(tokensToParse, req.getSession());%0A        resp.sendRedirect(%22/hello%22);%0A    %7D%0A%0A    private String getAuthorizationCode(HttpServletRequest req) %7B%0A        String authorizationCode = null;%0A        List%3CNameValuePair%3E queryString = URLEncodedUtils.p
+// Parse and obtain both access token and id token and save them in a persistent session%0A        parseTokensAndSaveToSession(tokensToP
 arse
-(
+, 
 req.get
-QueryString(), Charset.forName(%22ASCII%22));%0A%0A        for (NameValuePair pair : queryString) %7B%0A            if (%22code%22.equals(pair.getName())) %7B%0A                authorizationCode = pair.getValue();%0A            %7D%0A        %7D%0A        return authorizationCode
+Session());%0A%0A        // Redirect user to home%0A        resp.sendRedirect(%22/hello%22)
 ;%0A    %7D%0A
 %0A%0A%7D%0A
@@ -4133,12 +4133,10 @@
 ;%0A    %7D%0A
-%0A%0A
 %7D%0A

Reformat + Restyling.