package com.nubisware.oidc.rest; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class OpenIdConnectRESTHelper { protected static final Logger logger = LoggerFactory.getLogger(OpenIdConnectRESTHelper.class); public static String buildLoginUrl(String kcLoginUrl, String clientId, String state, String redirectUri) throws UnsupportedEncodingException { Map> params = new HashMap>(); params.put("client_id", Arrays.asList(URLEncoder.encode(clientId, "UTF-8"))); params.put("response_type", Arrays.asList("code")); params.put("scope", Arrays.asList("openid")); params.put("state", Arrays.asList(URLEncoder.encode(state, "UTF-8"))); params.put("redirect_uri", Arrays.asList(URLEncoder.encode(redirectUri, "UTF-8"))); params.put("login", Arrays.asList("true")); String q = mapToQueryString(params); return kcLoginUrl + "?" + q; } public static String mapToQueryString(Map> params) { String q = params.entrySet().stream().flatMap(p -> p.getValue().stream().map(v -> p.getKey() + "=" + v)) .reduce((p1, p2) -> p1 + "&" + p2).orElse(""); if (logger.isDebugEnabled()) { logger.debug("Query string is: " + q); } System.out.println("Query string is: " + q); return q; } public static JWTToken queryToken(String clientId, String tokenUrl, String code, String scope, String redirectUri) throws Exception { Map> params = new HashMap<>(); params.put("client_id", Arrays.asList(URLEncoder.encode(clientId, "UTF-8"))); params.put("grant_type", Arrays.asList("authorization_code")); params.put("scope", Arrays.asList(URLEncoder.encode(scope, "UTF-8"))); params.put("code", Arrays.asList(URLEncoder.encode(code, "UTF-8"))); params.put("redirect_uri", Arrays.asList(URLEncoder.encode(redirectUri, "UTF-8"))); return performQueryTokenWithPOST(tokenUrl, null, params); } public static JWTToken performQueryTokenWithPOST(String tokenUrl, String authorization, Map> params) throws Exception { if (logger.isDebugEnabled()) { logger.debug("Querying access token to Keycloak with URL: " + tokenUrl); } URL myurl = new URL(tokenUrl); HttpURLConnection con = (HttpURLConnection) myurl.openConnection(); con.setDoOutput(true); con.setDoInput(true); con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); con.setRequestProperty("Accept", "application/json"); con.setRequestProperty("Method", "POST"); if (authorization != null) { con.setRequestProperty("Authorization", authorization); } System.err.println("Authorization: " + authorization); OutputStream os = con.getOutputStream(); os.write(mapToQueryString(params).getBytes("UTF-8")); os.close(); StringBuilder sb = new StringBuilder(); int HttpResult = con.getResponseCode(); if (logger.isDebugEnabled()) { logger.debug(String.valueOf(con.getResponseCode())); logger.debug(con.getResponseMessage()); } if (HttpResult != HttpURLConnection.HTTP_OK) { BufferedReader br = new BufferedReader(new InputStreamReader(con.getErrorStream(), "UTF-8")); String line = null; while ((line = br.readLine()) != null) { sb.append(line + "\n"); } br.close(); throw new Exception("Unable to get token " + sb); } else { BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8")); String line = null; while ((line = br.readLine()) != null) { sb.append(line + "\n"); } br.close(); } return JWTToken.fromString(sb.toString()); } public static JWTToken queryUMAToken(String tokenUrl, String authorizationToken, String audience, List permissions) throws Exception { Map> params = new HashMap<>(); params.put("grant_type", Arrays.asList("urn:ietf:params:oauth:grant-type:uma-ticket")); params.put("audience", Arrays.asList(URLEncoder.encode(audience, "UTF-8"))); if (permissions != null && !permissions.isEmpty()) { params.put( "permission", permissions.stream().map(s -> { try { return URLEncoder.encode(s, "UTF-8"); } catch (UnsupportedEncodingException e) { return ""; } }).collect(Collectors.toList())); } return performQueryTokenWithPOST(tokenUrl, authorizationToken, params); } public static void logout(JWTToken token, String kcLogoutUrl, String portalClientId) throws IOException { Map> params = new HashMap<>(); params.put("client_id", Arrays.asList(URLEncoder.encode(portalClientId, "UTF-8"))); params.put("refresh_token", Arrays.asList(token.getRefreshTokenString())); logger.info("Performing logut from Keycloak with URL: " + kcLogoutUrl); URL myurl = new URL(kcLogoutUrl); HttpURLConnection con = (HttpURLConnection) myurl.openConnection(); con.setDoOutput(true); con.setDoInput(true); con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); con.setRequestProperty("Accept", "application/json"); con.setRequestProperty("Method", "POST"); con.setRequestProperty("Authorization", token.getAsBearer()); OutputStream os = con.getOutputStream(); os.write(mapToQueryString(params).getBytes("UTF-8")); os.close(); int responseCode = con.getResponseCode(); if (responseCode == 204) { logger.info("Logout performed correctly"); } else { logger.error("Cannot perfrom logout: [" + responseCode + "] " + con.getResponseMessage()); } } }