@Override public String getResourceName() { return delegate.getResourceName(); }
@Override public String getClientId() { return deployment.getResourceName(); }
@Override public void init(KeycloakDeployment deployment, Object config) { if (config == null || !(config instanceof Map)) { throw new RuntimeException("Configuration of jwt credentials by client secret is missing or incorrect for client '" + deployment.getResourceName() + "'. Check your adapter configuration"); } Map<String, Object> cfg = (Map<String, Object>) config; String clientSecretString = (String) cfg.get("secret"); if (clientSecretString == null) { throw new RuntimeException("Missing parameter secret-jwt in configuration of jwt for client " + deployment.getResourceName()); } setClientSecret(clientSecretString); }
@Override public void setClientCredentials(KeycloakDeployment deployment, Map<String, String> requestHeaders, Map<String, String> formParams) { String signedToken = createSignedRequestToken(deployment.getResourceName(), deployment.getRealmInfoUrl()); formParams.put(OAuth2Constants.CLIENT_ASSERTION_TYPE, OAuth2Constants.CLIENT_ASSERTION_TYPE_JWT); formParams.put(OAuth2Constants.CLIENT_ASSERTION, signedToken); }
@Override public void setClientCredentials(KeycloakDeployment deployment, Map<String, String> requestHeaders, Map<String, String> formParams) { String signedToken = createSignedRequestToken(deployment.getResourceName(), deployment.getRealmInfoUrl()); formParams.put(OAuth2Constants.CLIENT_ASSERTION_TYPE, OAuth2Constants.CLIENT_ASSERTION_TYPE_JWT); formParams.put(OAuth2Constants.CLIENT_ASSERTION, signedToken); }
@Override public void init(KeycloakDeployment deployment, Object config) { if (config == null || !(config instanceof Map)) { throw new RuntimeException("Configuration of jwt credentials is missing or incorrect for client '" + deployment.getResourceName() + "'. Check your adapter configuration"); } Map<String, Object> cfg = (Map<String, Object>) config; String clientKeystoreFile = (String) cfg.get("client-keystore-file"); if (clientKeystoreFile == null) { throw new RuntimeException("Missing parameter client-keystore-file in configuration of jwt for client " + deployment.getResourceName()); } String clientKeystoreType = (String) cfg.get("client-keystore-type"); KeystoreUtil.KeystoreFormat clientKeystoreFormat = clientKeystoreType==null ? KeystoreUtil.KeystoreFormat.JKS : Enum.valueOf(KeystoreUtil.KeystoreFormat.class, clientKeystoreType.toUpperCase()); String clientKeystorePassword = (String) cfg.get("client-keystore-password"); if (clientKeystorePassword == null) { throw new RuntimeException("Missing parameter client-keystore-password in configuration of jwt for client " + deployment.getResourceName()); } String clientKeyPassword = (String) cfg.get("client-key-password"); if (clientKeyPassword == null) { clientKeyPassword = clientKeystorePassword; } String clientKeyAlias = (String) cfg.get("client-key-alias"); if (clientKeyAlias == null) { clientKeyAlias = deployment.getResourceName(); } KeyPair keyPair = KeystoreUtil.loadKeyPairFromKeystore(clientKeystoreFile, clientKeystorePassword, clientKeyPassword, clientKeyAlias, clientKeystoreFormat); setupKeyPair(keyPair); this.tokenTimeout = asInt(cfg, "token-timeout", 10); }
public static void invokeClientManagementRequest(KeycloakDeployment deployment, String host, String endpointUrl) throws HttpFailure, IOException { if (endpointUrl == null) { throw new IOException("You need to configure URI for register/unregister node for application " + deployment.getResourceName()); } List<NameValuePair> formparams = new ArrayList<NameValuePair>(); formparams.add(new BasicNameValuePair(AdapterConstants.CLIENT_CLUSTER_HOST, host)); HttpPost post = new HttpPost(endpointUrl); ClientCredentialsProviderUtils.setClientCredentials(deployment, post, formparams); UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8"); post.setEntity(form); HttpResponse response = deployment.getClient().execute(post); int status = response.getStatusLine().getStatusCode(); if (status != 204) { HttpEntity entity = response.getEntity(); error(status, entity); } }
private void sendRequest(KeycloakDeployment deployment) { if (log.isTraceEnabled()) { log.trace("Going to send request to retrieve new set of realm public keys for client " + deployment.getResourceName()); } HttpGet getMethod = new HttpGet(deployment.getJwksUrl()); try { JSONWebKeySet jwks = HttpAdapterUtils.sendJsonHttpRequest(deployment, getMethod, JSONWebKeySet.class); Map<String, PublicKey> publicKeys = JWKSUtils.getKeysForUse(jwks, JWK.Use.SIG); if (log.isDebugEnabled()) { log.debug("Realm public keys successfully retrieved for client " + deployment.getResourceName() + ". New kids: " + publicKeys.keySet().toString()); } // Update current keys currentKeys.clear(); currentKeys.putAll(publicKeys); } catch (HttpClientAdapterException e) { log.error("Error when sending request to retrieve realm keys", e); } } }
@Override public void setClientCredentials(KeycloakDeployment deployment, Map<String, String> requestHeaders, Map<String, String> formParams) { String clientId = deployment.getResourceName(); if (!deployment.isPublicClient()) { if (clientSecret != null) { String authorization = BasicAuthHelper.createHeader(clientId, clientSecret); requestHeaders.put("Authorization", authorization); } else { logger.warnf("Client '%s' doesn't have secret available", clientId); } } else { formParams.put(OAuth2Constants.CLIENT_ID, clientId); } } }
public static ClientCredentialsProvider bootstrapClientAuthenticator(KeycloakDeployment deployment) { String clientId = deployment.getResourceName(); Map<String, Object> clientCredentials = deployment.getResourceCredentials(); String authenticatorId; if (clientCredentials == null || clientCredentials.isEmpty()) { authenticatorId = ClientIdAndSecretCredentialsProvider.PROVIDER_ID; } else { authenticatorId = (String) clientCredentials.get("provider"); if (authenticatorId == null) { // If there is just one credential type, use provider from it if (clientCredentials.size() == 1) { authenticatorId = clientCredentials.keySet().iterator().next(); } else { throw new RuntimeException("Can't identify clientAuthenticator from the configuration of client '" + clientId + "' . Check your adapter configurations"); } } } logger.debugf("Using provider '%s' for authentication of client '%s'", authenticatorId, clientId); Map<String, ClientCredentialsProvider> authenticators = new HashMap<>(); loadAuthenticators(authenticators, ClientCredentialsProviderUtils.class.getClassLoader()); loadAuthenticators(authenticators, Thread.currentThread().getContextClassLoader()); ClientCredentialsProvider authenticator = authenticators.get(authenticatorId); if (authenticator == null) { throw new RuntimeException("Couldn't find ClientCredentialsProvider implementation class with id: " + authenticatorId + ". Loaded authentication providers: " + authenticators.keySet()); } Object config = (clientCredentials==null) ? null : clientCredentials.get(authenticatorId); authenticator.init(deployment, config); return authenticator; }
public static Set<String> getRolesFromSecurityContext(RefreshableKeycloakSecurityContext session) { Set<String> roles = null; AccessToken accessToken = session.getToken(); if (session.getDeployment().isUseResourceRoleMappings()) { if (log.isTraceEnabled()) { log.trace("useResourceRoleMappings"); } AccessToken.Access access = accessToken.getResourceAccess(session.getDeployment().getResourceName()); if (access != null) roles = access.getRoles(); } else { if (log.isTraceEnabled()) { log.trace("use realm role mappings"); } AccessToken.Access access = accessToken.getRealmAccess(); if (access != null) roles = access.getRoles(); } if (roles == null) roles = Collections.emptySet(); if (log.isTraceEnabled()) { log.trace("Setting roles: "); for (String role : roles) { log.trace(" role: " + role); } } return roles; }
public void loginManual(PrintStream printer, Reader reader) throws IOException, ServerRequest.HttpFailure, VerificationException { CallbackListener callback = new CallbackListener(); callback.start(); String redirectUri = "urn:ietf:wg:oauth:2.0:oob"; String authUrl = deployment.getAuthUrl().clone() .queryParam(OAuth2Constants.CLIENT_ID, deployment.getResourceName()) .queryParam(OAuth2Constants.REDIRECT_URI, redirectUri) .build().toString(); printer.println("Open the following URL in a browser. After login copy/paste the code back and press <enter>"); printer.println(authUrl); printer.println(); printer.print("Code: "); String code = readCode(reader); processCode(code, redirectUri); status = Status.LOGGED_MANUAL; }
logger.info("Keycloak Client ID: " + deployment.getResourceName());
protected boolean validateAction(AdminAction action) { if (!action.validate()) { log.warn("admin request failed, not validated" + action.getAction()); facade.getResponse().sendError(400, "Not validated"); return false; } if (action.isExpired()) { log.warn("admin request failed, expired token"); facade.getResponse().sendError(400, "Expired token"); return false; } if (!deployment.getResourceName().equals(action.getResource())) { log.warn("Resource name does not match"); facade.getResponse().sendError(400, "Resource name does not match"); return false; } return true; }
/** * Verifies bearer token. Typically called when bearer token (access token) is sent to the service, which wants to verify it. Hence it also checks the audience in the token. * * @param tokenString * @param deployment * @return * @throws VerificationException */ public static AccessToken verifyToken(String tokenString, KeycloakDeployment deployment) throws VerificationException { TokenVerifier<AccessToken> tokenVerifier = createVerifier(tokenString, deployment, true, AccessToken.class); // Verify audience of bearer-token if (deployment.isVerifyTokenAudience()) { tokenVerifier.audience(deployment.getResourceName()); } return tokenVerifier.verify().getToken(); }
private HttpHandler sessionHandling(HttpHandler toWrap) { SessionCookieConfig sessionConfig = new SessionCookieConfig(); sessionConfig.setCookieName("keycloak." + deployment.getResourceName() + ".session"); sessionConfig.setPath(base); if (deployment.getSslRequired() == SslRequired.ALL) sessionConfig.setSecure(true); toWrap = new SessionAttachmentHandler( toWrap, sessionManager, sessionConfig); return toWrap; }
/** * Called after accessToken was verified (including signature, expiration etc) * */ protected Auth postTokenVerification(String tokenString, AccessToken token) { boolean verifyCaller; if (deployment.isUseResourceRoleMappings()) { verifyCaller = token.isVerifyCaller(deployment.getResourceName()); } else { verifyCaller = token.isVerifyCaller(); } if (verifyCaller) { throw new IllegalStateException("VerifyCaller not supported yet in login module"); } RefreshableKeycloakSecurityContext skSession = new RefreshableKeycloakSecurityContext(deployment, null, tokenString, token, null, null, null); String principalName = AdapterUtils.getPrincipalName(deployment, token); final KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = new KeycloakPrincipal<RefreshableKeycloakSecurityContext>(principalName, skSession); final Set<String> roles = AdapterUtils.getRolesFromSecurityContext(skSession); return new Auth(principal, roles, tokenString); }
/** * Verify access token and ID token. Typically called after successful tokenResponse is received from Keycloak * * @param accessTokenString * @param idTokenString * @param deployment * @return verified and parsed accessToken and idToken * @throws VerificationException */ public static VerifiedTokens verifyTokens(String accessTokenString, String idTokenString, KeycloakDeployment deployment) throws VerificationException { // Adapters currently do most of the checks including signature etc on the access token TokenVerifier<AccessToken> tokenVerifier = createVerifier(accessTokenString, deployment, true, AccessToken.class); AccessToken accessToken = tokenVerifier.verify().getToken(); if (idTokenString != null) { // Don't verify signature again on IDToken IDToken idToken = TokenVerifier.create(idTokenString, IDToken.class).getToken(); TokenVerifier<IDToken> idTokenVerifier = TokenVerifier.createWithoutSignature(idToken); // Always verify audience and azp on IDToken idTokenVerifier.audience(deployment.getResourceName()); idTokenVerifier.issuedFor(deployment.getResourceName()); idTokenVerifier.verify(); return new VerifiedTokens(accessToken, idToken); } else { return new VerifiedTokens(accessToken, null); } }
protected void completeAuthentication(BearerTokenRequestAuthenticator bearer, String method) { RefreshableKeycloakSecurityContext session = new RefreshableKeycloakSecurityContext(deployment, null, bearer.getTokenString(), bearer.getToken(), null, null, null); final KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = new KeycloakPrincipal<RefreshableKeycloakSecurityContext>(AdapterUtils.getPrincipalName(deployment, bearer.getToken()), session); completeBearerAuthentication(principal, method); log.debugv("User ''{0}'' invoking ''{1}'' on client ''{2}''", principal.getName(), facade.getRequest().getURI(), deployment.getResourceName()); }
protected void completeAuthentication(OAuthRequestAuthenticator oauth) { RefreshableKeycloakSecurityContext session = new RefreshableKeycloakSecurityContext(deployment, tokenStore, oauth.getTokenString(), oauth.getToken(), oauth.getIdTokenString(), oauth.getIdToken(), oauth.getRefreshToken()); final KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = new KeycloakPrincipal<RefreshableKeycloakSecurityContext>(AdapterUtils.getPrincipalName(deployment, oauth.getToken()), session); completeOAuthAuthentication(principal); log.debugv("User ''{0}'' invoking ''{1}'' on client ''{2}''", principal.getName(), facade.getRequest().getURI(), deployment.getResourceName()); }