| /** |
| ****************************************************************************** |
| * Copyright © 2017-2018 PTA GmbH. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| ****************************************************************************** |
| */ |
| package org.eclipse.openk.portal.auth2.util; |
| |
| import java.nio.charset.StandardCharsets; |
| import javax.ws.rs.core.MediaType; |
| import org.eclipse.openk.portal.auth2.model.JwtHeader; |
| import org.eclipse.openk.portal.auth2.model.JwtPayload; |
| import org.eclipse.openk.portal.auth2.model.JwtToken; |
| import org.eclipse.openk.portal.auth2.model.KeyCloakRole; |
| import org.eclipse.openk.portal.auth2.model.KeyCloakUser; |
| import com.google.gson.JsonSyntaxException; |
| import com.google.gson.reflect.TypeToken; |
| import java.io.BufferedReader; |
| import java.io.DataOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.InputStreamReader; |
| import java.lang.reflect.Type; |
| import java.net.HttpURLConnection; |
| import java.net.URL; |
| import java.util.List; |
| import org.apache.log4j.Logger; |
| import org.eclipse.openk.portal.common.BackendConfig; |
| import org.eclipse.openk.portal.common.JsonGeneratorBase; |
| import org.eclipse.openk.portal.exceptions.PortalInternalServerError; |
| import org.keycloak.common.util.Base64Url; |
| |
| public class JwtHelper { |
| |
| private static final Logger logger = Logger.getLogger(JwtHelper.class.getName()); |
| |
| private JwtHelper() { |
| } |
| |
| public static JwtToken login(String user, String password) throws PortalInternalServerError { |
| String token = sendPost(BackendConfig.getInstance().getAuthServerUrl() + "auth/realms/" + |
| BackendConfig.getInstance().getKeycloakRealm() + "/protocol/openid-connect/token", |
| "username=" + user + "&password=" + password + "&client_id=" |
| + BackendConfig.getInstance().getKeycloakClient() + "&grant_type=password"); |
| return getJwtTokenFromJson(token); |
| } |
| |
| public static boolean serviceAvailable() throws PortalInternalServerError { |
| String jsonRet = sendGet(BackendConfig.getInstance().getAuthServerUrl() + "auth/realms/" + |
| BackendConfig.getInstance().getKeycloakRealm(), "", null); |
| |
| return jsonRet != null ? jsonRet.contains("realm") && jsonRet.contains(BackendConfig.getInstance().getKeycloakRealm()) |
| : false; |
| } |
| |
| public static List<KeyCloakUser> getUsers(JwtToken jwtToken, int maxUsers) throws PortalInternalServerError { |
| String users = sendGet(BackendConfig.getInstance().getAuthServerUrl() + "auth/admin/realms/" + BackendConfig.getInstance().getKeycloakRealm() + "/users?max="+maxUsers, |
| MediaType.APPLICATION_JSON, jwtToken.getAccessToken()); |
| return getUserListFromJson(users); |
| } |
| |
| public static List<KeyCloakRole> getRolesForUser(JwtToken jwtToken, String id) throws PortalInternalServerError { |
| String roles = sendGet(BackendConfig.getInstance().getAuthServerUrl() + "auth/admin/realms/" + BackendConfig.getInstance().getKeycloakRealm() + "/users/" + id + "/role-mappings/realm", |
| MediaType.APPLICATION_JSON, jwtToken.getAccessToken()); |
| return getRolesListFromJson(roles); |
| } |
| |
| public static JwtHeader getJwtHeaderFromJson(String json) { |
| return JsonGeneratorBase.getGson().fromJson(json, JwtHeader.class); |
| } |
| |
| public static JwtPayload getJwtPayloadFromJson(String json) { |
| return JsonGeneratorBase.getGson().fromJson(json, JwtPayload.class); |
| } |
| |
| public static JwtToken getJwtTokenFromJson(String json) { |
| return JsonGeneratorBase.getGson().fromJson(json, JwtToken.class); |
| } |
| |
| public static List<KeyCloakUser> getUserListFromJson(String json) throws PortalInternalServerError { |
| try { |
| Type listType = new TypeToken<List<KeyCloakUser>>() { |
| }.getType(); |
| return JsonGeneratorBase.getGson().fromJson(json, listType); |
| } catch (JsonSyntaxException ex) { |
| logger.error("Error in getUserListFromJson", ex); |
| throw new PortalInternalServerError("JsonSyntaxException"); |
| } |
| } |
| |
| public static List<KeyCloakRole> getRolesListFromJson(String json) throws PortalInternalServerError { |
| try { |
| Type listType = new TypeToken<List<KeyCloakRole>>() { |
| }.getType(); |
| return JsonGeneratorBase.getGson().fromJson(json, listType); |
| } catch (JsonSyntaxException ex) { |
| logger.error("Error in getRolesListFromJson", ex); |
| throw new PortalInternalServerError("JsonSyntaxException"); |
| } |
| } |
| |
| public static JwtPayload getPayLoad(JwtToken token) { |
| String[] parts = token.getAccessToken().split("[.]"); |
| |
| //parts[0] is the jwtHeader |
| String jwtPayload = parts[1]; |
| //parts[2] is the jwtVerifySignature |
| |
| // decode |
| byte[] decoded = Base64Url.decode(jwtPayload); |
| jwtPayload = new String(decoded, StandardCharsets.UTF_8); |
| logger.info(jwtPayload); |
| return getJwtPayloadFromJson(jwtPayload); |
| } |
| |
| private static HttpURLConnection getHttpConnection(String targetUrl) throws PortalInternalServerError { |
| try { |
| URL url = new URL(targetUrl); |
| return (HttpURLConnection) url.openConnection(); |
| } catch (IOException e) { |
| logger.error(e); |
| throw new PortalInternalServerError("HttpURLConnection IOException"); |
| } |
| } |
| |
| private static String sendGet(String targetUrl, String accept, String token) throws PortalInternalServerError { |
| logger.info("sendGet"); |
| |
| HttpURLConnection con = getHttpConnection(targetUrl); |
| StringBuilder response = new StringBuilder(); // or StringBuffer if Java version 5+ |
| |
| try (AutoCloseable conc = con::disconnect) { |
| con.setRequestMethod("GET"); |
| con.setRequestProperty("Accept", accept); |
| con.setInstanceFollowRedirects(false); |
| if (token != null) // is authenticated |
| { |
| con.setRequestProperty("Authorization", "Bearer " + token); |
| } |
| InputStream is = con.getInputStream(); |
| try (BufferedReader rd = new BufferedReader(new InputStreamReader(is))) { |
| String line; |
| while ((line = rd.readLine()) != null) { |
| response.append(line); |
| response.append('\r'); |
| logger.info("Got line -> " + line); |
| } |
| } |
| logger.info("sendGet was successful"); |
| return response.toString(); |
| } catch (Exception e) { |
| logger.error("Error occured in sendGet: " + e); |
| return null; |
| } |
| } |
| |
| private static String sendPost(String targetUrl, String urlParameters) throws PortalInternalServerError { |
| logger.info("sendPost"); |
| |
| HttpURLConnection con = getHttpConnection(targetUrl); |
| StringBuilder response = new StringBuilder(); // or StringBuffer if Java version 5+ |
| |
| try (AutoCloseable conc = con::disconnect) { |
| con.setRequestMethod("POST"); |
| con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); |
| con.setRequestProperty("Accept", MediaType.APPLICATION_JSON); |
| con.setRequestProperty("Content-Length", Integer.toString(urlParameters.getBytes().length)); |
| con.setInstanceFollowRedirects(false); |
| con.setDoOutput(true); |
| // Send request |
| try (DataOutputStream wr = new DataOutputStream(con.getOutputStream())) { |
| wr.writeBytes(urlParameters); |
| } |
| // Get Response |
| InputStream is = con.getInputStream(); |
| |
| try (BufferedReader rd = new BufferedReader(new InputStreamReader(is))) { |
| String line; |
| while ((line = rd.readLine()) != null) { |
| response.append(line); |
| response.append('\r'); |
| } |
| } |
| |
| return response.toString(); |
| } catch (Exception e) { |
| logger.error("Error occured in sendPost: " + e); |
| return null; |
| } |
| } |
| |
| public static String formatToken(String accessToken) { |
| return accessToken != null ? accessToken.replace("Bearer", "").trim() : ""; |
| } |
| } |