Search in sources :

Example 1 with AccessToken

use of org.keycloak.representations.AccessToken in project keycloak by keycloak.

the class AdapterTokenVerifier method verifyTokens.

/**
 * 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);
    }
}
Also used : AccessToken(org.keycloak.representations.AccessToken) IDToken(org.keycloak.representations.IDToken)

Example 2 with AccessToken

use of org.keycloak.representations.AccessToken in project keycloak by keycloak.

the class AbstractPolicyEnforcer method authorize.

public AuthorizationContext authorize(OIDCHttpFacade httpFacade) {
    EnforcementMode enforcementMode = getEnforcerConfig().getEnforcementMode();
    KeycloakSecurityContext securityContext = httpFacade.getSecurityContext();
    if (EnforcementMode.DISABLED.equals(enforcementMode)) {
        if (securityContext == null) {
            httpFacade.getResponse().sendError(401, "Invalid bearer");
        }
        return createEmptyAuthorizationContext(true);
    }
    Request request = httpFacade.getRequest();
    PathConfig pathConfig = getPathConfig(request);
    if (securityContext == null) {
        if (!isDefaultAccessDeniedUri(request)) {
            if (pathConfig != null) {
                if (EnforcementMode.DISABLED.equals(pathConfig.getEnforcementMode())) {
                    return createEmptyAuthorizationContext(true);
                } else {
                    challenge(pathConfig, getRequiredScopes(pathConfig, request), httpFacade);
                }
            } else {
                handleAccessDenied(httpFacade);
            }
        }
        return createEmptyAuthorizationContext(false);
    }
    AccessToken accessToken = securityContext.getToken();
    if (accessToken != null) {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debugf("Checking permissions for path [%s] with config [%s].", request.getURI(), pathConfig);
        }
        if (pathConfig == null) {
            if (EnforcementMode.PERMISSIVE.equals(enforcementMode)) {
                return createAuthorizationContext(accessToken, null);
            }
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debugf("Could not find a configuration for path [%s]", getPath(request));
            }
            if (isDefaultAccessDeniedUri(request)) {
                return createAuthorizationContext(accessToken, null);
            }
            handleAccessDenied(httpFacade);
            return createEmptyAuthorizationContext(false);
        }
        if (EnforcementMode.DISABLED.equals(pathConfig.getEnforcementMode())) {
            return createAuthorizationContext(accessToken, pathConfig);
        }
        MethodConfig methodConfig = getRequiredScopes(pathConfig, request);
        Map<String, List<String>> claims = resolveClaims(pathConfig, httpFacade);
        if (isAuthorized(pathConfig, methodConfig, accessToken, httpFacade, claims)) {
            try {
                return createAuthorizationContext(accessToken, pathConfig);
            } catch (Exception e) {
                throw new RuntimeException("Error processing path [" + pathConfig.getPath() + "].", e);
            }
        }
        if (methodConfig != null && ScopeEnforcementMode.DISABLED.equals(methodConfig.getScopesEnforcementMode())) {
            return createEmptyAuthorizationContext(true);
        }
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debugf("Sending challenge to the client. Path [%s]", pathConfig);
        }
        if (!challenge(pathConfig, methodConfig, httpFacade)) {
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debugf("Challenge not sent, sending default forbidden response. Path [%s]", pathConfig);
            }
            handleAccessDenied(httpFacade);
        }
    }
    return createEmptyAuthorizationContext(false);
}
Also used : MethodConfig(org.keycloak.representations.adapters.config.PolicyEnforcerConfig.MethodConfig) PathConfig(org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig) KeycloakSecurityContext(org.keycloak.KeycloakSecurityContext) AccessToken(org.keycloak.representations.AccessToken) ScopeEnforcementMode(org.keycloak.representations.adapters.config.PolicyEnforcerConfig.ScopeEnforcementMode) EnforcementMode(org.keycloak.representations.adapters.config.PolicyEnforcerConfig.EnforcementMode) Request(org.keycloak.adapters.spi.HttpFacade.Request) ArrayList(java.util.ArrayList) List(java.util.List)

Example 3 with AccessToken

use of org.keycloak.representations.AccessToken in project keycloak by keycloak.

the class AuthenticatedActionsHandler method corsRequest.

protected boolean corsRequest() {
    if (!deployment.isCors())
        return false;
    KeycloakSecurityContext securityContext = facade.getSecurityContext();
    String origin = facade.getRequest().getHeader(CorsHeaders.ORIGIN);
    origin = "null".equals(origin) ? null : origin;
    String exposeHeaders = deployment.getCorsExposedHeaders();
    if (deployment.getPolicyEnforcer() != null) {
        if (exposeHeaders != null) {
            exposeHeaders += ",";
        } else {
            exposeHeaders = "";
        }
        exposeHeaders += "WWW-Authenticate";
    }
    String requestOrigin = UriUtils.getOrigin(facade.getRequest().getURI());
    log.debugv("Origin: {0} uri: {1}", origin, facade.getRequest().getURI());
    if (securityContext != null && origin != null && !origin.equals(requestOrigin)) {
        AccessToken token = securityContext.getToken();
        Set<String> allowedOrigins = token.getAllowedOrigins();
        log.debugf("Allowed origins in token: %s", allowedOrigins);
        if (allowedOrigins == null || (!allowedOrigins.contains("*") && !allowedOrigins.contains(origin))) {
            if (allowedOrigins == null) {
                log.debugv("allowedOrigins was null in token");
            } else {
                log.debugv("allowedOrigins did not contain origin");
            }
            facade.getResponse().sendError(403);
            facade.getResponse().end();
            return true;
        }
        log.debugv("returning origin: {0}", origin);
        facade.getResponse().setStatus(200);
        facade.getResponse().setHeader(CorsHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, origin);
        facade.getResponse().setHeader(CorsHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
        if (exposeHeaders != null) {
            facade.getResponse().setHeader(CorsHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, exposeHeaders);
        }
    } else {
        log.debugv("cors validation not needed as we are not a secure session or origin header was null: {0}", facade.getRequest().getURI());
    }
    return false;
}
Also used : KeycloakSecurityContext(org.keycloak.KeycloakSecurityContext) AccessToken(org.keycloak.representations.AccessToken)

Example 4 with AccessToken

use of org.keycloak.representations.AccessToken in project keycloak by keycloak.

the class TokenCallable method call.

@Override
public String call() {
    if (tokenResponse == null) {
        tokenResponse = obtainTokens();
    }
    try {
        String rawAccessToken = tokenResponse.getToken();
        AccessToken accessToken = JsonSerialization.readValue(new JWSInput(rawAccessToken).getContent(), AccessToken.class);
        if (accessToken.isActive() && this.isTokenTimeToLiveSufficient(accessToken)) {
            return rawAccessToken;
        } else {
            log.debug("Access token is expired.");
        }
    } catch (Exception cause) {
        clearTokens();
        throw new RuntimeException("Failed to parse access token", cause);
    }
    tokenResponse = tryRefreshToken();
    return tokenResponse.getToken();
}
Also used : AccessToken(org.keycloak.representations.AccessToken) JWSInput(org.keycloak.jose.jws.JWSInput)

Example 5 with AccessToken

use of org.keycloak.representations.AccessToken in project keycloak by keycloak.

the class UserInfoEndpoint method issueUserInfo.

private Response issueUserInfo(String tokenString) {
    cors = Cors.add(request).auth().allowedMethods(request.getHttpMethod()).auth().exposedHeaders(Cors.ACCESS_CONTROL_ALLOW_METHODS);
    try {
        session.clientPolicy().triggerOnEvent(new UserInfoRequestContext(tokenString));
    } catch (ClientPolicyException cpe) {
        throw new CorsErrorResponseException(cors.allowAllOrigins(), cpe.getError(), cpe.getErrorDetail(), cpe.getErrorStatus());
    }
    EventBuilder event = new EventBuilder(realm, session, clientConnection).event(EventType.USER_INFO_REQUEST).detail(Details.AUTH_METHOD, Details.VALIDATE_ACCESS_TOKEN);
    if (tokenString == null) {
        event.error(Errors.INVALID_TOKEN);
        throw new CorsErrorResponseException(cors.allowAllOrigins(), OAuthErrorException.INVALID_REQUEST, "Token not provided", Response.Status.BAD_REQUEST);
    }
    AccessToken token;
    ClientModel clientModel = null;
    try {
        TokenVerifier<AccessToken> verifier = TokenVerifier.create(tokenString, AccessToken.class).withDefaultChecks().realmUrl(Urls.realmIssuer(session.getContext().getUri().getBaseUri(), realm.getName()));
        SignatureVerifierContext verifierContext = session.getProvider(SignatureProvider.class, verifier.getHeader().getAlgorithm().name()).verifier(verifier.getHeader().getKeyId());
        verifier.verifierContext(verifierContext);
        token = verifier.verify().getToken();
        clientModel = realm.getClientByClientId(token.getIssuedFor());
        if (clientModel == null) {
            event.error(Errors.CLIENT_NOT_FOUND);
            throw new CorsErrorResponseException(cors.allowAllOrigins(), OAuthErrorException.INVALID_REQUEST, "Client not found", Response.Status.BAD_REQUEST);
        }
        cors.allowedOrigins(session, clientModel);
        TokenVerifier.createWithoutSignature(token).withChecks(NotBeforeCheck.forModel(clientModel), new TokenManager.TokenRevocationCheck(session)).verify();
    } catch (VerificationException e) {
        if (clientModel == null) {
            cors.allowAllOrigins();
        }
        event.error(Errors.INVALID_TOKEN);
        throw newUnauthorizedErrorResponseException(OAuthErrorException.INVALID_TOKEN, "Token verification failed");
    }
    if (!clientModel.getProtocol().equals(OIDCLoginProtocol.LOGIN_PROTOCOL)) {
        event.error(Errors.INVALID_CLIENT);
        throw new CorsErrorResponseException(cors, Errors.INVALID_CLIENT, "Wrong client protocol.", Response.Status.BAD_REQUEST);
    }
    session.getContext().setClient(clientModel);
    event.client(clientModel);
    if (!clientModel.isEnabled()) {
        event.error(Errors.CLIENT_DISABLED);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "Client disabled", Response.Status.BAD_REQUEST);
    }
    UserSessionModel userSession = findValidSession(token, event, clientModel);
    UserModel userModel = userSession.getUser();
    if (userModel == null) {
        event.error(Errors.USER_NOT_FOUND);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "User not found", Response.Status.BAD_REQUEST);
    }
    event.user(userModel).detail(Details.USERNAME, userModel.getUsername());
    // https://tools.ietf.org/html/draft-ietf-oauth-mtls-08#section-3
    if (OIDCAdvancedConfigWrapper.fromClientModel(clientModel).isUseMtlsHokToken()) {
        if (!MtlsHoKTokenUtil.verifyTokenBindingWithClientCertificate(token, request, session)) {
            event.error(Errors.NOT_ALLOWED);
            throw newUnauthorizedErrorResponseException(OAuthErrorException.UNAUTHORIZED_CLIENT, "Client certificate missing, or its thumbprint and one in the refresh token did NOT match");
        }
    }
    // Existence of authenticatedClientSession for our client already handled before
    AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(clientModel.getId());
    // Retrieve by latest scope parameter
    ClientSessionContext clientSessionCtx = DefaultClientSessionContext.fromClientSessionScopeParameter(clientSession, session);
    AccessToken userInfo = new AccessToken();
    tokenManager.transformUserInfoAccessToken(session, userInfo, userSession, clientSessionCtx);
    Map<String, Object> claims = tokenManager.generateUserInfoClaims(userInfo, userModel);
    Response.ResponseBuilder responseBuilder;
    OIDCAdvancedConfigWrapper cfg = OIDCAdvancedConfigWrapper.fromClientModel(clientModel);
    if (cfg.isUserInfoSignatureRequired()) {
        String issuerUrl = Urls.realmIssuer(session.getContext().getUri().getBaseUri(), realm.getName());
        String audience = clientModel.getClientId();
        claims.put("iss", issuerUrl);
        claims.put("aud", audience);
        String signatureAlgorithm = session.tokens().signatureAlgorithm(TokenCategory.USERINFO);
        SignatureProvider signatureProvider = session.getProvider(SignatureProvider.class, signatureAlgorithm);
        SignatureSignerContext signer = signatureProvider.signer();
        String signedUserInfo = new JWSBuilder().type("JWT").jsonContent(claims).sign(signer);
        responseBuilder = Response.ok(signedUserInfo).header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JWT);
        event.detail(Details.SIGNATURE_REQUIRED, "true");
        event.detail(Details.SIGNATURE_ALGORITHM, cfg.getUserInfoSignedResponseAlg().toString());
    } else {
        responseBuilder = Response.ok(claims).header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
        event.detail(Details.SIGNATURE_REQUIRED, "false");
    }
    event.success();
    return cors.builder(responseBuilder).build();
}
Also used : UserSessionModel(org.keycloak.models.UserSessionModel) SignatureVerifierContext(org.keycloak.crypto.SignatureVerifierContext) OIDCAdvancedConfigWrapper(org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper) SignatureSignerContext(org.keycloak.crypto.SignatureSignerContext) AuthenticatedClientSessionModel(org.keycloak.models.AuthenticatedClientSessionModel) ClientPolicyException(org.keycloak.services.clientpolicy.ClientPolicyException) JWSBuilder(org.keycloak.jose.jws.JWSBuilder) UserModel(org.keycloak.models.UserModel) Response(javax.ws.rs.core.Response) HttpResponse(org.jboss.resteasy.spi.HttpResponse) ClientModel(org.keycloak.models.ClientModel) SignatureProvider(org.keycloak.crypto.SignatureProvider) UserInfoRequestContext(org.keycloak.services.clientpolicy.context.UserInfoRequestContext) EventBuilder(org.keycloak.events.EventBuilder) DefaultClientSessionContext(org.keycloak.services.util.DefaultClientSessionContext) ClientSessionContext(org.keycloak.models.ClientSessionContext) AccessToken(org.keycloak.representations.AccessToken) VerificationException(org.keycloak.common.VerificationException) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException)

Aggregations

AccessToken (org.keycloak.representations.AccessToken)230 Test (org.junit.Test)129 OAuthClient (org.keycloak.testsuite.util.OAuthClient)104 AbstractKeycloakTest (org.keycloak.testsuite.AbstractKeycloakTest)54 RefreshToken (org.keycloak.representations.RefreshToken)45 AuthorizationResponse (org.keycloak.representations.idm.authorization.AuthorizationResponse)37 JWSInput (org.keycloak.jose.jws.JWSInput)29 Permission (org.keycloak.representations.idm.authorization.Permission)28 EventRepresentation (org.keycloak.representations.idm.EventRepresentation)27 Response (javax.ws.rs.core.Response)26 ClientResource (org.keycloak.admin.client.resource.ClientResource)22 VerificationException (org.keycloak.common.VerificationException)19 ClientRepresentation (org.keycloak.representations.idm.ClientRepresentation)19 AccessTokenResponse (org.keycloak.representations.AccessTokenResponse)18 IDToken (org.keycloak.representations.IDToken)18 AuthorizationRequest (org.keycloak.representations.idm.authorization.AuthorizationRequest)17 IOException (java.io.IOException)15 AuthzClient (org.keycloak.authorization.client.AuthzClient)15 ResourceRepresentation (org.keycloak.representations.idm.authorization.ResourceRepresentation)14 ArrayList (java.util.ArrayList)13