package code; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URL; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.ArrayList; import java.util.List; import javax.net.ssl.HttpsURLConnection; import org.apache.commons.codec.binary.Base64; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; public class ObtainToken implements HttpHandler{ private KeyCloak kcs; private String state; private String codeVerifier; public ObtainToken(KeyCloak kcs) { this.kcs = kcs; } @Override public void handle(HttpExchange exchange) throws IOException { URI requestURI = exchange.getRequestURI(); String stringURI = requestURI.toString(); boolean wantsRedirectPage = Helper.compareText(stringURI,URI.create("/").toString()); boolean wantsToken = Helper.compareText(stringURI,URI.create("/secured").toString()); if(wantsToken) System.out.println("URI = "+exchange.getRequestURI().getPath()); if(!wantsRedirectPage && !wantsToken) { String error = "Invalid URI"; OutputStream os = exchange.getResponseBody(); exchange.sendResponseHeaders(400, error.getBytes().length); os.write(error.getBytes()); os.close(); return; } String requestMethod = exchange.getRequestMethod(); if (Helper.compareText(requestMethod, "GET")) { if(wantsRedirectPage) { codeVerifier = createRandomString(); try { String codeChallenge = createCodeChallenge(codeVerifier); state = createRandomString(); //An opaque arbitrary alphanumeric string your app adds to the initial request that Auth0 includes when redirecting back to your application. String nonce = "a81e1a84-8885-4702-b8d1-f6c5a0d1fc4d"; // System.out.println("CODE VERIFIER = "+codeVerifier); // get the html page List<String> strlist = new ArrayList<>(); String response = null; response = getRedirectPage(); strlist.add("text/html"); if(response != null && !Helper.compareText(response, "fail")){ response = response.replace("$DOMAIN", kcs.authServer()) .replace("$REALM", kcs.realm()) .replace("$MY_CODE_CHALLENGE", codeChallenge) .replace("$MY_CLIENT_ID", kcs.clientId()) .replace("$MY_REDIRECT_URI", kcs.redirectUri()) .replace("$MY_NONCE",nonce) .replace("$MY_STATE", state); exchange.getResponseHeaders().put("content-type", strlist); exchange.sendResponseHeaders(200, response.getBytes().length); OutputStream os = exchange.getResponseBody(); os.write(response.getBytes()); os.close(); } else { exchange.sendResponseHeaders(500, response.getBytes().length); OutputStream os = exchange.getResponseBody(); os.write(response.getBytes()); os.close(); } } catch (UnsupportedEncodingException | NoSuchAlgorithmException e) { System.out.println("Error during creation of code challenge"); } } if(wantsToken) { // NON FUNZIONA PERCHE' LA String[] arr = stringURI.split("/secured"); for(int i=0; i<arr.length; i++) System.out.println(arr[i]); System.out.println("lunghezza = "+arr.length); String allParamsString = stringURI.split("/secured")[1]; System.out.println("allParamsString = "+allParamsString); String[] allParamsArray = allParamsString.split("&"); String state = allParamsArray[0]; if(!this.state.equals(state)) { Helper.badRequest(exchange); return; } String authCode = allParamsArray[2]; // request token String httpsURL = "http://"+kcs.authServer()+"/realms/"+kcs.realm()+"/protocol/openid-connect/token"; URL myUrl = new URL(httpsURL); // SSLUtilities.trustAllHttpsCertificates(); // SSLUtilities.trustAllHostnames(); HttpsURLConnection conn = (HttpsURLConnection)myUrl.openConnection(); conn.setReadTimeout(7000); conn.setConnectTimeout(7000); conn.setRequestMethod("POST"); conn.setDoOutput(true); conn.setDoInput(true); conn.setRequestProperty("content-type", "application/x-www-form-urlencoded"); String body = "grant_type=authorization_code" + "&client_id="+kcs.clientId() + "&code_verifier="+codeVerifier + "&code="+authCode + "&redirect_uri=https://localhost:3000/secured"; OutputStream outputStream = conn.getOutputStream(); outputStream.write(body.getBytes("UTF-8")); outputStream.close(); String inputLine; InputStream is = conn.getInputStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); String response = ""; while ((inputLine = br.readLine()) != null) { response += inputLine; } br.close(); System.out.println(response); // String answer = response.replace(remoteHOST,localHOST); } } else { Helper.methodNotAllowed(exchange); } } private static String getRedirectPage() { String line; String page = Server.CLIENT_PATH+"/redirect.html"; StringBuilder answer = new StringBuilder(); if (getExtension(page).length() == 0) page += ".html"; BufferedReader bufferedReader = null; try { FileReader fileReader = new FileReader(page); bufferedReader = new BufferedReader(fileReader); boolean isComment = false; while ((line = bufferedReader.readLine()) != null) { line = line.trim(); if(line.startsWith("<!--") && line.endsWith("-->")) { continue; } if(line.startsWith("<!--")) { isComment = true; continue; } if(line.endsWith("-->")) { isComment = false; continue; } if(!isComment && line.length()>0) answer.append(line).append("\n"); } } catch (FileNotFoundException ex) { System.out.println("Unable to open file '" + page + "'"); return "fail"; } catch (IOException ex) { System.out.println("Error reading file '" + page + "'"); return "fail"; } finally { try{ if(bufferedReader != null) bufferedReader.close(); } catch (IOException ex){ System.out.println("Error closing bufferedReader"); } } return answer.toString(); } private static String getExtension(String file) { int i = file.length() - 1; while (i > 0 && file.charAt(i) != '.' && file.charAt(i) != '/') i--; if (file.charAt(i) == '.') return file.substring(i + 1); else return ""; } private String createRandomString() { SecureRandom sr = new SecureRandom(); byte[] code = new byte[32]; sr.nextBytes(code); return java.util.Base64.getUrlEncoder().withoutPadding().encodeToString(code); } private String createCodeChallenge(String verifier) throws UnsupportedEncodingException, NoSuchAlgorithmException { byte[] bytes = verifier.getBytes("US-ASCII"); MessageDigest md = MessageDigest.getInstance("SHA-256"); md.update(bytes, 0, bytes.length); byte[] digest = md.digest(); return Base64.encodeBase64URLSafeString(digest); } }