package code; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.nio.charset.StandardCharsets; import java.security.NoSuchAlgorithmException; import java.sql.SQLException; import java.util.ArrayList; import java.util.Base64; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import db.DBC; import db.Dominio; import io.fusionauth.jwt.InvalidJWTSignatureException; import io.fusionauth.jwt.Verifier; import io.fusionauth.jwt.domain.Algorithm; import io.fusionauth.jwt.domain.JWT; import io.fusionauth.jwt.rsa.RSAVerifier; public class TokenHandler implements HttpHandler { public void handle(HttpExchange he) throws IOException { // URI requestedUri = he.getRequestURI(); String requestMethod = he.getRequestMethod(); if (requestMethod.compareToIgnoreCase("options") == 0) { Helper.sendCors(he, 200); return; } if (requestMethod.compareToIgnoreCase("GET") != 0) { // send Method not allowed // exchange.getResponseHeaders().remove("content-type"); // String response = "{\"message\":\"Method not allowed!\"}"; // Helper.sendCors(he,405,response); Helper.sendCors(he, 405); return; } // String query = requestedUri.getRawQuery(); // String body = readBody(he.getRequestBody()); String user; // String user = he.getRequestHeaders().get("user").get(0); // questo e' strano: headers dice { {} } mentre headers.get("Authorization") // riporta il token correttamente // System.out.println("Headers: "+he.getRequestHeaders()); // System.out.println("Auth: "+he.getRequestHeaders().get("Authorization")); // System.out.println("token: " + token); if ((user = Helper.checkTokenGetUser(he)) == null) { Helper.sendCors(he, 401); return; } // System.out.println(body); // JSONObject chiave = new JSONObject(); // chiamo http://localhost:8080/auth/realms/test00/protocol/openid-connect/certs // //probabilmente https // TOKEN____________________________________________________________________ // { // "access_token": // "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJXZ2FCRjhidS05dVhhR0pNRzIxQWQtQTV3aW0xZ29oRnhNNXVvNTJrLWhJIn0.eyJleHAiOjE2NjIwMjQwMjgsImlhdCI6MTY2MjAyMzcyOCwiYXV0aF90aW1lIjoxNjYyMDIzNjYyLCJqdGkiOiIzMmUwODFmMi00MmZhLTQ2ZDEtOTliNy05OWY0MTRlNmM4MTciLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvcmVhbG1zL3Rlc3QwMCIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiI2MGE4MjdjMS0zZDM3LTQ4ODEtYjU3Ny0zODNlZDUxNjE3MjgiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJteWNsaWVudCIsIm5vbmNlIjoiYTgxZTFhODQtODg4NS00NzAyLWI4ZDEtZjZjNWEwZDFmYzRkIiwic2Vzc2lvbl9zdGF0ZSI6IjUyOTQwYWYzLTM0MjctNDVkZC04YWNhLWE0ZDYxMjdhNDQxZCIsImFjciI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cDovL2xvY2FsaG9zdDozMDAwIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvZmZsaW5lX2FjY2VzcyIsImRlZmF1bHQtcm9sZXMtdGVzdDAwIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIiwic2lkIjoiNTI5NDBhZjMtMzQyNy00NWRkLThhY2EtYTRkNjEyN2E0NDFkIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoiTWFyaW8gUm9zc2kiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJqb2huIiwiZ2l2ZW5fbmFtZSI6Ik1hcmlvIiwiZmFtaWx5X25hbWUiOiJSb3NzaSIsImVtYWlsIjoibWFyaW9AZ21haWwuY29tIn0.JQEmBY9zqVBelNorT3ZNyjXk6Bh0QbR1UO_1MTquS39njq8Fvd1h5ygan_v-YtlcTD9gz38O1OLhZEnK6QoUlUNfBybPrgM8GxcqTnmwYe2I5bJQ_7U6lqdWjgPJTBpLmy7faTj6_i2t0jVNKfTxJgzzbsTiYhJZZp-jvu05ZyMaQ3Q_wUYazb6VvbAkz9F2-8Uk04SxHVUsHjcinoyYd6jQP5TML3cVvwNk_eX2LavQk9o3XCQeBxsq9tUw7HsnSjtvPnuqHMe7S_Yg7_xp6QLVXdQAkOebFcvAMv8hMUMhXk0RV-RryhvQ85gF5NHgdvFhB6FPoXCO-T-SZpi6Qw", // "expires_in": 300, // "refresh_expires_in": 1800, // "refresh_token": // "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJkZDIyM2U5NC1mMjUxLTQ4MDAtYTI3Zi1jYzQzZjZhZTQzODEifQ.eyJleHAiOjE2NjIwMjU1MjgsImlhdCI6MTY2MjAyMzcyOCwianRpIjoiOTEwNWViMGUtMGJmMS00ODRlLTk1M2UtOGRmMTRkMzkwMGI4IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy90ZXN0MDAiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvcmVhbG1zL3Rlc3QwMCIsInN1YiI6IjYwYTgyN2MxLTNkMzctNDg4MS1iNTc3LTM4M2VkNTE2MTcyOCIsInR5cCI6IlJlZnJlc2giLCJhenAiOiJteWNsaWVudCIsIm5vbmNlIjoiYTgxZTFhODQtODg4NS00NzAyLWI4ZDEtZjZjNWEwZDFmYzRkIiwic2Vzc2lvbl9zdGF0ZSI6IjUyOTQwYWYzLTM0MjctNDVkZC04YWNhLWE0ZDYxMjdhNDQxZCIsInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwiLCJzaWQiOiI1Mjk0MGFmMy0zNDI3LTQ1ZGQtOGFjYS1hNGQ2MTI3YTQ0MWQifQ.ZqcOLMUwHPxQY2I0V9bPIy6TBTeUIcHEbxgnxhJrac0", // "token_type": "Bearer", // "id_token": // "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJXZ2FCRjhidS05dVhhR0pNRzIxQWQtQTV3aW0xZ29oRnhNNXVvNTJrLWhJIn0.eyJleHAiOjE2NjIwMjQwMjgsImlhdCI6MTY2MjAyMzcyOCwiYXV0aF90aW1lIjoxNjYyMDIzNjYyLCJqdGkiOiI5ZDEyYzUyZi1kZTdlLTQ4ZDctOTEzOC01Yjc5NGRjZjJmZDQiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvcmVhbG1zL3Rlc3QwMCIsImF1ZCI6Im15Y2xpZW50Iiwic3ViIjoiNjBhODI3YzEtM2QzNy00ODgxLWI1NzctMzgzZWQ1MTYxNzI4IiwidHlwIjoiSUQiLCJhenAiOiJteWNsaWVudCIsIm5vbmNlIjoiYTgxZTFhODQtODg4NS00NzAyLWI4ZDEtZjZjNWEwZDFmYzRkIiwic2Vzc2lvbl9zdGF0ZSI6IjUyOTQwYWYzLTM0MjctNDVkZC04YWNhLWE0ZDYxMjdhNDQxZCIsImF0X2hhc2giOiJ5MGVaZGowZmZsbFBMN3U3SkxiSzFnIiwiYWNyIjoiMSIsInNpZCI6IjUyOTQwYWYzLTM0MjctNDVkZC04YWNhLWE0ZDYxMjdhNDQxZCIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwibmFtZSI6Ik1hcmlvIFJvc3NpIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiam9obiIsImdpdmVuX25hbWUiOiJNYXJpbyIsImZhbWlseV9uYW1lIjoiUm9zc2kiLCJlbWFpbCI6Im1hcmlvQGdtYWlsLmNvbSJ9.SjyYBuj4bz7ugyqJibNubaUmwUvuyiocPXrr745PQ8f-AzhI_ITxjG3m7_i9lRw_UpcPQrlSwZTPxhDFUS2eK8YGG4Qg_MEELO6Pvez25x1aLrfDRw2qiT8Eu5t-6fa_N7ztQtWuyw9ThMxmpBdGx3PBDimjIY7m9CHrgSEymJf2LJsC2CF68WvczDEoVVzoUikwmvFbVS1LWCCAOd7b3s07fqP61kyj_XFtcyZv29EIOlUsodPKdQhNiplBNU1st-l0pLRocGEvIjRngSQDzTW4aHAL-jQENW2od0N23IXKtTrPCx33gElfeuA9hvyb6c4d8CNFrw6AHKH0YsoGqQ", // "not-before-policy": 0, // "session_state": "52940af3-3427-45dd-8aca-a4d6127a441d", // "scope": "openid profile email" // } // CHIAVE // PUBBLICA________________________________________________________________ // { // "keys": [ // { // "kid": "WgaBF8bu-9uXaGJMG21Ad-A5wim1gohFxM5uo52k-hI", // "kty": "RSA", // "alg": "RS256", // "use": "sig", // "n": // "qoJMLXqIHoBKq5vE7EYVdvxpwqOjPkeTUSb1rdhJs8ZpfCOQk7PYlNu-ykl4PAjYS5sVs5gQSzEwtTZ3vz1y8Ry0V1Xa3c3wk77NzahMO9QnAXa0cqFWhaIr4l0oKhRy-57hNIthkiRuDDlWBREb5sqk8OWxarznEVRykaC4178ccQrv6T3T5VGzxV1lCcBDzQchx_c9_v-tcQVGeyBhdm9uFARbxGG-91kDxSv3MKQbjdwp9csr2QDwuFgcBSB4Ul-9oMCZiVDpgWuoCy_ZxsI22WYAPT8KyaYts-0v7B89hPPweR7TzbmQHEGMfl0U_qEBdQw0N9P2KRapol7RyQ", // "e": "AQAB", // "x5c": [ // "MIICmzCCAYMCBgGCkqLMcTANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZ0ZXN0MDAwHhcNMjIwODEyMTUxNjU4WhcNMzIwODEyMTUxODM4WjARMQ8wDQYDVQQDDAZ0ZXN0MDAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqgkwteogegEqrm8TsRhV2/GnCo6M+R5NRJvWt2Emzxml8I5CTs9iU277KSXg8CNhLmxWzmBBLMTC1Nne/PXLxHLRXVdrdzfCTvs3NqEw71CcBdrRyoVaFoiviXSgqFHL7nuE0i2GSJG4MOVYFERvmyqTw5bFqvOcRVHKRoLjXvxxxCu/pPdPlUbPFXWUJwEPNByHH9z3+/61xBUZ7IGF2b24UBFvEYb73WQPFK/cwpBuN3Cn1yyvZAPC4WBwFIHhSX72gwJmJUOmBa6gLL9nGwjbZZgA9PwrJpi2z7S/sHz2E8/B5HtPNuZAcQYx+XRT+oQF1DDQ30/YpFqmiXtHJAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAHF8qo6bVlpt/44OxqnSFDY0wIxcunFIbA05ggox/5oAQvdoTD1LB8sfuLa3dtA/ysnnZDytk+vr8V4feYdSvAbtCWVq3yJgt7Dhe7ueP45v4WPJPcPqv8kMYtbkh0mivF2mYVLsEbZK46kBXN4Gkpv1oRDl2b04rfO7abv0dqb3eFs5QiJtKd1az1ckrTYFHdcB5TiiMaPq8/ikmInYKMvRW5H+NmjRvQf6dhKaSj1+cgcZ5xwVlOuubUyJHABKcK6dfnznwA/Ri3fzYXnG5p7mDazdeOQlNRHMK5SM2D6QRunmufg8ulmM+vhxg5ri8o1WqIkA03z+w44vQFy28Xo=" // ], // "x5t": "ip8I56vsh3-VgNBfzigD3oiIwsg", // "x5t#S256": "1aZ1N3a_PeHLpZeLIbyfyqUjUKJ9NYWMP7-9H2arYWM" // }, // { // "kid": "-0j9GoUrm6Fjs8sxcwaNe9R9mqr7bmgSRQ_nRp72iIs", // "kty": "RSA", // "alg": "RSA-OAEP", // "use": "enc", // "n": // "kpxC6pFuQnQVq8KoO3uMaFrfKC00jBbHfkx8HYuCIblQGap3xjcLGfMbd2EP2Hz2c38dmWcCMS6GgxUU10rlnWc4HKZ5jYCVTEdjU4nkmArzVipG03HzVb-3Eftz1hb4z8Qyjw616tjwQtaQRCvtx9o_UhmxG6YIeJhauN_Zh9z6ZHJ8bY6N242vk_ryJmaTsQ-GyOmU5h16mMrGCjMJ_uMiy38dITySNFGKwnJHaKU8H6V25UuGVgNl-Wjpk5L2bAdSkDEblJ7SsvzoYLGYzCUeCHhztWbNOy_sc31awULdTWEgH8SKvOWf3qZY1siItHBqHLHlHo5lNIMzhowGrw", // "e": "AQAB", // "x5c": [ // "MIICmzCCAYMCBgGCkqLNYTANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZ0ZXN0MDAwHhcNMjIwODEyMTUxNjU5WhcNMzIwODEyMTUxODM5WjARMQ8wDQYDVQQDDAZ0ZXN0MDAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCSnELqkW5CdBWrwqg7e4xoWt8oLTSMFsd+THwdi4IhuVAZqnfGNwsZ8xt3YQ/YfPZzfx2ZZwIxLoaDFRTXSuWdZzgcpnmNgJVMR2NTieSYCvNWKkbTcfNVv7cR+3PWFvjPxDKPDrXq2PBC1pBEK+3H2j9SGbEbpgh4mFq439mH3Ppkcnxtjo3bja+T+vImZpOxD4bI6ZTmHXqYysYKMwn+4yLLfx0hPJI0UYrCckdopTwfpXblS4ZWA2X5aOmTkvZsB1KQMRuUntKy/OhgsZjMJR4IeHO1Zs07L+xzfVrBQt1NYSAfxIq85Z/epljWyIi0cGocseUejmU0gzOGjAavAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAE9kzDnbCjywK6QXECR8citVNaqarf3QQYDzSNakWgrGTTjdStASwEsPJvYJJ5Q6tl6ndqv4gflKq8STrmlHd4Ly+QHnXDwzrzjuSydZDAjYVcacMpZ4PAOAci0R6AmXTynIzyxU92LOlOWiF3ChG7uMRq7yLCNWo1jZxUepGo5z9LyIRGO4Pb878nhWL5PvXC95/vnbx2hSN7T6Uft3j3/94+fgIP4rmO2IWsDuc6fza/J07fK42Mtysy6FqBwhrimDMq+3OnTmdhSRL4pVVrRPSpYO/Czw9ra8hgGoAhu4G4FhTKAr8K75QaMdTtShpBMVNrImOq9kHtOoZJCJW0g=" // ], // "x5t": "AU5GWMxLtE_hFDiJevWYEql-n4A", // "x5t#S256": "43Rx3Dsp6j_NLNwVx__Pb6mz07KrCa8xzH0pKOoV06g" // } // ] // } // The x5c filed value is copied between —–BEGIN CERTIFICATE—– // // —–END CERTIFICATE—– directives . // Build an EC verifier using an EC Public Key. A verifier may also be built // using the PublicKey object. // Verifier verifier = ECVerifier.newVerifier(Paths.get("public_key.pem")); // // // Verify and decode the encoded string JWT to a rich object // JWT jwt = JWT.getDecoder().decode(encodedJWT, verifier); // // // Assert the subject of the JWT is as expected // assertEquals(jwt.subject, "f1e33ab3-027f-47c5-bb07-8dd8ab37a2d3"); // verifica token // if token !ok return // try { // verificaToken(token,signature); // } catch (NoSuchAlgorithmException | IOException | JSONException e1) { // e1.printStackTrace(); // } // ricavo da token JSONObject res = new JSONObject(); JSONArray rs = new JSONArray(); ArrayList<String> domList; try { domList = DBC.getDomainsUser(user); for (String k : domList) { JSONObject ogg = new JSONObject(); ogg.put("nome", k); Dominio d = DBC.getDomain(k); ogg.put("stato", d.getStatus()); ogg.put("admin", false); rs.put(ogg); } domList.clear(); domList = DBC.getDomainsAdmin(user); for (String k : domList) { JSONObject ogg = new JSONObject(); ogg.put("nome", k);// domain Dominio d = DBC.getDomain(k); ogg.put("stato", d.getStatus()); ogg.put("admin", true); rs.put(ogg); } res.put("response", rs); } catch (SQLException | JSONException e) { e.printStackTrace(); return; } String response = res.toString(); Helper.sendCors(he, 200, response); // JSONObject j=new JSONObject(); // j.append("User", DBC.getDomainsUser(user)); // j=(""+":"+); } public static String verificaToken(String encodedJWT, String signature) throws IOException, JSONException, NoSuchAlgorithmException { URL url = new URL( Helper.getKeycloakURL() + "realms/" + Helper.getKeycloakRealm() + "/protocol/openid-connect/certs");// maybe, // se // CloudAppe // è // localhost // porta // 8080 HttpURLConnection con = (HttpURLConnection) url.openConnection(); // 3000/install da inserire con.setRequestMethod("GET"); con.setRequestProperty("Content-Type", "application/json"); con.setRequestProperty("Accept", "application/json"); con.setDoOutput(true); con.setConnectTimeout(5000); con.setReadTimeout(5000); // DataOutputStream out = new DataOutputStream(con.getOutputStream());// // inserimento param in call // out.writeBytes(j.toString());// // ParameterStringBuilder.getParamsString(parameters)); // out.flush(); // out.close(); // con.setRequestProperty("Content-Type", "application/json"); // String contentType = con.getHeaderField("Content-Type"); // leggo risposta int status = con.getResponseCode(); BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); String inputLine; StringBuffer content = new StringBuffer(); while ((inputLine = in.readLine()) != null) { content.append(inputLine); } in.close(); con.disconnect(); JSONObject j = new JSONObject(content.toString()); JSONArray arr = j.getJSONArray("keys"); JSONObject ogg = arr.getJSONObject(0); String chiave = ogg.getJSONArray("x5c").get(0).toString(); String cert = "-----BEGIN CERTIFICATE-----\n" + chiave + "\n-----END CERTIFICATE-----"; Verifier verifier = RSAVerifier.newVerifier(cert); try { int index = encodedJWT.lastIndexOf('.'); byte[] message = encodedJWT.substring(0, index).getBytes(StandardCharsets.UTF_8); // message = token.header + token.body (tokSplit[0]+"."+tokSplit[1]) byte[] signatureBytes = Base64.getUrlDecoder().decode(signature);// signature = tokSplit[2] verifier.verify(Algorithm.RS256, message, signatureBytes); } catch (InvalidJWTSignatureException e) { return null; } // Verify and decode the encoded string JWT to a rich object JWT jwt = JWT.getDecoder().decode(encodedJWT, verifier); /* * { * "aud" : "account", * "exp" : 1662288513, * "iat" : 1662288213, * "iss" : "http://localhost:8080/realms/test00", * "sub" : "60a827c1-3d37-4881-b577-383ed5161728", * "jti" : "719379f0-0b22-40fd-ae35-0f523ffd9d4e", * "auth_time" : 1662285948, * "typ" : "Bearer", * "azp" : "myclient", * "nonce" : "a81e1a84-8885-4702-b8d1-f6c5a0d1fc4d", * "session_state" : "969cdd2d-07db-4366-8180-d1ff15ddce20", * "acr" : "0", * "allowed-origins" : [ "http://localhost:3000" ], * "realm_access" : { * "roles" : [ "offline_access", "default-roles-test00", "uma_authorization" ] * }, * "resource_access" : { * "account" : { * "roles" : [ "manage-account", "manage-account-links", "view-profile" ] * } * }, * "scope" : "openid profile email", * "sid" : "969cdd2d-07db-4366-8180-d1ff15ddce20", * "email_verified" : false, * "name" : "Mario Rossi", * "preferred_username" : "john", * "given_name" : "Mario", * "family_name" : "Rossi", * "email" : "mario@gmail.com" * } */ return jwt.getString("preferred_username"); } }