Search in sources :

Example 1 with CorsErrorResponseException

use of org.keycloak.services.CorsErrorResponseException in project keycloak by keycloak.

the class DeviceGrantType method oauth2DeviceFlow.

public Response oauth2DeviceFlow() {
    if (!realm.getOAuth2DeviceConfig().isOAuth2DeviceAuthorizationGrantEnabled(client)) {
        event.error(Errors.NOT_ALLOWED);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT, "Client not allowed OAuth 2.0 Device Authorization Grant", Response.Status.BAD_REQUEST);
    }
    String deviceCode = formParams.getFirst(OAuth2Constants.DEVICE_CODE);
    if (deviceCode == null) {
        event.error(Errors.INVALID_OAUTH2_DEVICE_CODE);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "Missing parameter: " + OAuth2Constants.DEVICE_CODE, Response.Status.BAD_REQUEST);
    }
    OAuth2DeviceTokenStoreProvider store = session.getProvider(OAuth2DeviceTokenStoreProvider.class);
    OAuth2DeviceCodeModel deviceCodeModel = store.getByDeviceCode(realm, deviceCode);
    if (deviceCodeModel == null) {
        event.error(Errors.INVALID_OAUTH2_DEVICE_CODE);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT, "Device code not valid", Response.Status.BAD_REQUEST);
    }
    if (deviceCodeModel.isExpired()) {
        event.error(Errors.EXPIRED_OAUTH2_DEVICE_CODE);
        throw new CorsErrorResponseException(cors, OAuthErrorException.EXPIRED_TOKEN, "Device code is expired", Response.Status.BAD_REQUEST);
    }
    if (!store.isPollingAllowed(deviceCodeModel)) {
        event.error(Errors.SLOW_DOWN);
        throw new CorsErrorResponseException(cors, OAuthErrorException.SLOW_DOWN, "Slow down", Response.Status.BAD_REQUEST);
    }
    if (deviceCodeModel.isDenied()) {
        event.error(Errors.ACCESS_DENIED);
        throw new CorsErrorResponseException(cors, OAuthErrorException.ACCESS_DENIED, "The end user denied the authorization request", Response.Status.BAD_REQUEST);
    }
    if (deviceCodeModel.isPending()) {
        throw new CorsErrorResponseException(cors, OAuthErrorException.AUTHORIZATION_PENDING, "The authorization request is still pending", Response.Status.BAD_REQUEST);
    }
    // https://tools.ietf.org/html/rfc7636#section-4.6
    String codeVerifier = formParams.getFirst(OAuth2Constants.CODE_VERIFIER);
    String codeChallenge = deviceCodeModel.getCodeChallenge();
    String codeChallengeMethod = deviceCodeModel.getCodeChallengeMethod();
    if (codeChallengeMethod != null && !codeChallengeMethod.isEmpty()) {
        PkceUtils.checkParamsForPkceEnforcedClient(codeVerifier, codeChallenge, codeChallengeMethod, null, null, event, cors);
    } else {
        // PKCE Activation is OFF, execute the codes implemented in KEYCLOAK-2604
        PkceUtils.checkParamsForPkceNotEnforcedClient(codeVerifier, codeChallenge, codeChallengeMethod, null, null, event, cors);
    }
    // Approved
    String userSessionId = deviceCodeModel.getUserSessionId();
    event.detail(Details.CODE_ID, userSessionId);
    event.session(userSessionId);
    // Retrieve UserSession
    UserSessionModel userSession = new UserSessionCrossDCManager(session).getUserSessionWithClient(realm, userSessionId, client.getId());
    if (userSession == null) {
        userSession = session.sessions().getUserSession(realm, userSessionId);
        if (userSession == null) {
            throw new CorsErrorResponseException(cors, OAuthErrorException.AUTHORIZATION_PENDING, "The authorization request is verified but can not lookup the user session yet", Response.Status.BAD_REQUEST);
        }
    }
    // Now, remove the device code
    store.removeDeviceCode(realm, deviceCode);
    UserModel user = userSession.getUser();
    if (user == null) {
        event.error(Errors.USER_NOT_FOUND);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT, "User not found", Response.Status.BAD_REQUEST);
    }
    event.user(userSession.getUser());
    if (!user.isEnabled()) {
        event.error(Errors.USER_DISABLED);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT, "User disabled", Response.Status.BAD_REQUEST);
    }
    AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
    if (!client.getClientId().equals(clientSession.getClient().getClientId())) {
        event.error(Errors.INVALID_CODE);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT, "Auth error", Response.Status.BAD_REQUEST);
    }
    if (!AuthenticationManager.isSessionValid(realm, userSession)) {
        event.error(Errors.USER_SESSION_NOT_FOUND);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT, "Session not active", Response.Status.BAD_REQUEST);
    }
    try {
        session.clientPolicy().triggerOnEvent(new DeviceTokenRequestContext(deviceCodeModel, formParams));
    } catch (ClientPolicyException cpe) {
        event.error(cpe.getError());
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT, cpe.getErrorDetail(), Response.Status.BAD_REQUEST);
    }
    // Compute client scopes again from scope parameter. Check if user still has them granted
    // (but in device_code-to-token request, it could just theoretically happen that they are not available)
    String scopeParam = deviceCodeModel.getScope();
    if (!TokenManager.verifyConsentStillAvailable(session, user, client, TokenManager.getRequestedClientScopes(scopeParam, client))) {
        event.error(Errors.NOT_ALLOWED);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_SCOPE, "Client no longer has requested consent from user", Response.Status.BAD_REQUEST);
    }
    ClientSessionContext clientSessionCtx = DefaultClientSessionContext.fromClientSessionAndScopeParameter(clientSession, scopeParam, session);
    // Set nonce as an attribute in the ClientSessionContext. Will be used for the token generation
    clientSessionCtx.setAttribute(OIDCLoginProtocol.NONCE_PARAM, deviceCodeModel.getNonce());
    return tokenEndpoint.createTokenResponse(user, userSession, clientSessionCtx, scopeParam, false);
}
Also used : OAuth2DeviceTokenStoreProvider(org.keycloak.models.OAuth2DeviceTokenStoreProvider) UserModel(org.keycloak.models.UserModel) UserSessionModel(org.keycloak.models.UserSessionModel) DeviceTokenRequestContext(org.keycloak.protocol.oidc.grants.device.clientpolicy.context.DeviceTokenRequestContext) DefaultClientSessionContext(org.keycloak.services.util.DefaultClientSessionContext) ClientSessionContext(org.keycloak.models.ClientSessionContext) OAuth2DeviceCodeModel(org.keycloak.models.OAuth2DeviceCodeModel) AuthenticatedClientSessionModel(org.keycloak.models.AuthenticatedClientSessionModel) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException) UserSessionCrossDCManager(org.keycloak.services.managers.UserSessionCrossDCManager) ClientPolicyException(org.keycloak.services.clientpolicy.ClientPolicyException)

Example 2 with CorsErrorResponseException

use of org.keycloak.services.CorsErrorResponseException 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)

Example 3 with CorsErrorResponseException

use of org.keycloak.services.CorsErrorResponseException in project keycloak by keycloak.

the class CibaGrantType method createUserSession.

private UserSessionModel createUserSession(CIBAAuthenticationRequest request, Map<String, String> additionalParams) {
    RootAuthenticationSessionModel rootAuthSession = session.authenticationSessions().createRootAuthenticationSession(realm);
    // here Client Model of CD(Consumption Device) needs to be used to bind its Client Session with User Session.
    AuthenticationSessionModel authSession = rootAuthSession.createAuthenticationSession(client);
    authSession.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
    authSession.setAction(AuthenticatedClientSessionModel.Action.AUTHENTICATE.name());
    authSession.setClientNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(session.getContext().getUri().getBaseUri(), realm.getName()));
    authSession.setClientNote(OIDCLoginProtocol.SCOPE_PARAM, request.getScope());
    if (additionalParams != null) {
        for (String paramName : additionalParams.keySet()) {
            authSession.setClientNote(ADDITIONAL_CALLBACK_PARAMS_PREFIX + paramName, additionalParams.get(paramName));
        }
    }
    if (request.getOtherClaims() != null) {
        for (String paramName : request.getOtherClaims().keySet()) {
            authSession.setClientNote(ADDITIONAL_BACKCHANNEL_REQ_PARAMS_PREFIX + paramName, request.getOtherClaims().get(paramName).toString());
        }
    }
    UserModel user = session.users().getUserById(realm, request.getSubject());
    if (user == null) {
        event.error(Errors.USERNAME_MISSING);
        throw new ErrorResponseException(OAuthErrorException.INVALID_GRANT, "Could not identify user", Response.Status.BAD_REQUEST);
    }
    if (!user.isEnabled()) {
        event.error(Errors.USER_DISABLED);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT, "User disabled", Response.Status.BAD_REQUEST);
    }
    logger.debugf("CIBA Grant :: user model found. user.getId() = %s, user.getEmail() = %s, user.getUsername() = %s.", user.getId(), user.getEmail(), user.getUsername());
    authSession.setAuthenticatedUser(user);
    if (user.getRequiredActionsStream().count() > 0) {
        event.error(Errors.RESOLVE_REQUIRED_ACTIONS);
        throw new ErrorResponseException(OAuthErrorException.INVALID_GRANT, "Account is not fully set up", Response.Status.BAD_REQUEST);
    }
    AuthenticationManager.setClientScopesInSession(authSession);
    ClientSessionContext context = AuthenticationProcessor.attachSession(authSession, null, session, realm, session.getContext().getConnection(), event);
    UserSessionModel userSession = context.getClientSession().getUserSession();
    if (userSession == null) {
        event.error(Errors.USER_SESSION_NOT_FOUND);
        throw new ErrorResponseException(OAuthErrorException.INVALID_GRANT, "User session is not found", Response.Status.BAD_REQUEST);
    }
    // authorization (consent)
    UserConsentModel grantedConsent = session.users().getConsentByClient(realm, user.getId(), client.getId());
    if (grantedConsent == null) {
        grantedConsent = new UserConsentModel(client);
        session.users().addConsent(realm, user.getId(), grantedConsent);
        if (logger.isTraceEnabled()) {
            grantedConsent.getGrantedClientScopes().forEach(i -> logger.tracef("CIBA Grant :: Consent granted. %s", i.getName()));
        }
    }
    boolean updateConsentRequired = false;
    for (String clientScopeId : authSession.getClientScopes()) {
        ClientScopeModel clientScope = KeycloakModelUtils.findClientScopeById(realm, client, clientScopeId);
        if (clientScope != null && !grantedConsent.isClientScopeGranted(clientScope) && clientScope.isDisplayOnConsentScreen()) {
            grantedConsent.addGrantedClientScope(clientScope);
            updateConsentRequired = true;
        }
    }
    if (updateConsentRequired) {
        session.users().updateConsent(realm, user.getId(), grantedConsent);
        if (logger.isTraceEnabled()) {
            grantedConsent.getGrantedClientScopes().forEach(i -> logger.tracef("CIBA Grant :: Consent updated. %s", i.getName()));
        }
    }
    event.detail(Details.CONSENT, Details.CONSENT_VALUE_CONSENT_GRANTED);
    event.detail(Details.CODE_ID, userSession.getId());
    event.session(userSession.getId());
    event.user(user);
    logger.debugf("Successfully verified Authe Req Id '%s'. User session: '%s', client: '%s'", request, userSession.getId(), client.getId());
    return userSession;
}
Also used : UserModel(org.keycloak.models.UserModel) AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) UserSessionModel(org.keycloak.models.UserSessionModel) DefaultClientSessionContext(org.keycloak.services.util.DefaultClientSessionContext) ClientSessionContext(org.keycloak.models.ClientSessionContext) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) ErrorResponseException(org.keycloak.services.ErrorResponseException) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException) ClientScopeModel(org.keycloak.models.ClientScopeModel) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException) UserConsentModel(org.keycloak.models.UserConsentModel)

Example 4 with CorsErrorResponseException

use of org.keycloak.services.CorsErrorResponseException in project keycloak by keycloak.

the class CibaGrantType method cibaGrant.

public Response cibaGrant() {
    ProfileHelper.requireFeature(Profile.Feature.CIBA);
    if (!realm.getCibaPolicy().isOIDCCIBAGrantEnabled(client)) {
        event.error(Errors.NOT_ALLOWED);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT, "Client not allowed OIDC CIBA Grant", Response.Status.BAD_REQUEST);
    }
    String jwe = formParams.getFirst(AUTH_REQ_ID);
    if (jwe == null) {
        event.error(Errors.INVALID_CODE);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "Missing parameter: " + AUTH_REQ_ID, Response.Status.BAD_REQUEST);
    }
    logger.tracev("CIBA Grant :: authReqId = {0}", jwe);
    CIBAAuthenticationRequest request;
    try {
        request = CIBAAuthenticationRequest.deserialize(session, jwe);
    } catch (Exception e) {
        logger.warnf("illegal format of auth_req_id : e.getMessage() = %s", e.getMessage());
        // Auth Req ID has not put onto cache, no need to remove Auth Req ID.
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT, "Invalid Auth Req ID", Response.Status.BAD_REQUEST);
    }
    request.setClient(client);
    try {
        session.clientPolicy().triggerOnEvent(new BackchannelTokenRequestContext(request, formParams));
    } catch (ClientPolicyException cpe) {
        event.error(cpe.getError());
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT, cpe.getErrorDetail(), Response.Status.BAD_REQUEST);
    }
    OAuth2DeviceTokenStoreProvider store = session.getProvider(OAuth2DeviceTokenStoreProvider.class);
    OAuth2DeviceCodeModel deviceCode = store.getByDeviceCode(realm, request.getId());
    if (deviceCode == null) {
        // Auth Req ID has not put onto cache, no need to remove Auth Req ID.
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT, "Invalid " + AUTH_REQ_ID, Response.Status.BAD_REQUEST);
    }
    if (!request.getIssuedFor().equals(client.getClientId())) {
        logDebug("invalid client.", request);
        // the client sending this Auth Req ID does not match the client to which keycloak had issued Auth Req ID.
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT, "unauthorized client", Response.Status.BAD_REQUEST);
    }
    if (deviceCode.isExpired()) {
        logDebug("expired.", request);
        throw new CorsErrorResponseException(cors, OAuthErrorException.EXPIRED_TOKEN, "authentication timed out", Response.Status.BAD_REQUEST);
    }
    if (!store.isPollingAllowed(deviceCode)) {
        logDebug("pooling.", request);
        throw new CorsErrorResponseException(cors, OAuthErrorException.SLOW_DOWN, "too early to access", Response.Status.BAD_REQUEST);
    }
    if (deviceCode.isDenied()) {
        logDebug("denied.", request);
        throw new CorsErrorResponseException(cors, OAuthErrorException.ACCESS_DENIED, "not authorized", Response.Status.BAD_REQUEST);
    }
    // get corresponding Authentication Channel Result entry
    if (deviceCode.isPending()) {
        logDebug("not yet authenticated by Authentication Device or auth_req_id has already been used to get tokens.", request);
        throw new CorsErrorResponseException(cors, OAuthErrorException.AUTHORIZATION_PENDING, "The authorization request is still pending as the end-user hasn't yet been authenticated.", Response.Status.BAD_REQUEST);
    }
    UserSessionModel userSession = createUserSession(request, deviceCode.getAdditionalParams());
    UserModel user = userSession.getUser();
    store.removeDeviceCode(realm, request.getId());
    // Compute client scopes again from scope parameter. Check if user still has them granted
    // (but in code-to-token request, it could just theoretically happen that they are not available)
    String scopeParam = request.getScope();
    if (!TokenManager.verifyConsentStillAvailable(session, user, client, TokenManager.getRequestedClientScopes(scopeParam, client))) {
        event.error(Errors.NOT_ALLOWED);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_SCOPE, "Client no longer has requested consent from user", Response.Status.BAD_REQUEST);
    }
    ClientSessionContext clientSessionCtx = DefaultClientSessionContext.fromClientSessionAndScopeParameter(userSession.getAuthenticatedClientSessionByClient(client.getId()), scopeParam, session);
    int authTime = Time.currentTime();
    userSession.setNote(AuthenticationManager.AUTH_TIME, String.valueOf(authTime));
    return tokenEndpoint.createTokenResponse(user, userSession, clientSessionCtx, scopeParam, true);
}
Also used : OAuth2DeviceTokenStoreProvider(org.keycloak.models.OAuth2DeviceTokenStoreProvider) UserModel(org.keycloak.models.UserModel) UserSessionModel(org.keycloak.models.UserSessionModel) DefaultClientSessionContext(org.keycloak.services.util.DefaultClientSessionContext) ClientSessionContext(org.keycloak.models.ClientSessionContext) OAuth2DeviceCodeModel(org.keycloak.models.OAuth2DeviceCodeModel) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException) BackchannelTokenRequestContext(org.keycloak.protocol.oidc.grants.ciba.clientpolicy.context.BackchannelTokenRequestContext) CIBAAuthenticationRequest(org.keycloak.protocol.oidc.grants.ciba.channel.CIBAAuthenticationRequest) OAuthErrorException(org.keycloak.OAuthErrorException) ErrorResponseException(org.keycloak.services.ErrorResponseException) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException) ClientPolicyException(org.keycloak.services.clientpolicy.ClientPolicyException) CibaRootEndpoint(org.keycloak.protocol.oidc.grants.ciba.endpoints.CibaRootEndpoint) TokenEndpoint(org.keycloak.protocol.oidc.endpoints.TokenEndpoint) ClientPolicyException(org.keycloak.services.clientpolicy.ClientPolicyException)

Example 5 with CorsErrorResponseException

use of org.keycloak.services.CorsErrorResponseException in project keycloak by keycloak.

the class PkceUtils method verifyCodeVerifier.

public static void verifyCodeVerifier(String codeVerifier, String codeChallenge, String codeChallengeMethod, String authUserId, String authUsername, EventBuilder event, Cors cors) {
    if (!isValidPkceCodeVerifier(codeVerifier)) {
        logger.infof("PKCE invalid code verifier");
        event.error(Errors.INVALID_CODE_VERIFIER);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT, "PKCE invalid code verifier", Response.Status.BAD_REQUEST);
    }
    logger.debugf("PKCE supporting Client, codeVerifier = %s", codeVerifier);
    String codeVerifierEncoded = codeVerifier;
    try {
        // plain or S256
        if (codeChallengeMethod != null && codeChallengeMethod.equals(OAuth2Constants.PKCE_METHOD_S256)) {
            logger.debugf("PKCE codeChallengeMethod = %s", codeChallengeMethod);
            codeVerifierEncoded = PkceUtils.generateS256CodeChallenge(codeVerifier);
        } else {
            logger.debug("PKCE codeChallengeMethod is plain");
            codeVerifierEncoded = codeVerifier;
        }
    } catch (Exception nae) {
        logger.infof("PKCE code verification failed, not supported algorithm specified");
        event.error(Errors.PKCE_VERIFICATION_FAILED);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT, "PKCE code verification failed, not supported algorithm specified", Response.Status.BAD_REQUEST);
    }
    if (!codeChallenge.equals(codeVerifierEncoded)) {
        logger.warnf("PKCE verification failed. authUserId = %s, authUsername = %s", authUserId, authUsername);
        event.error(Errors.PKCE_VERIFICATION_FAILED);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_GRANT, "PKCE verification failed", Response.Status.BAD_REQUEST);
    } else {
        logger.debugf("PKCE verification success. codeVerifierEncoded = %s, codeChallenge = %s", codeVerifierEncoded, codeChallenge);
    }
}
Also used : CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException) OAuthErrorException(org.keycloak.OAuthErrorException)

Aggregations

CorsErrorResponseException (org.keycloak.services.CorsErrorResponseException)30 UserSessionModel (org.keycloak.models.UserSessionModel)13 UserModel (org.keycloak.models.UserModel)11 ClientSessionContext (org.keycloak.models.ClientSessionContext)10 ClientModel (org.keycloak.models.ClientModel)9 ClientPolicyException (org.keycloak.services.clientpolicy.ClientPolicyException)9 OAuthErrorException (org.keycloak.OAuthErrorException)8 AccessTokenResponse (org.keycloak.representations.AccessTokenResponse)8 DefaultClientSessionContext (org.keycloak.services.util.DefaultClientSessionContext)8 Response (javax.ws.rs.core.Response)7 AuthenticationSessionModel (org.keycloak.sessions.AuthenticationSessionModel)6 RootAuthenticationSessionModel (org.keycloak.sessions.RootAuthenticationSessionModel)6 AuthorizationProvider (org.keycloak.authorization.AuthorizationProvider)5 AuthenticatedClientSessionModel (org.keycloak.models.AuthenticatedClientSessionModel)5 TokenManager (org.keycloak.protocol.oidc.TokenManager)5 AccessToken (org.keycloak.representations.AccessToken)5 AuthenticationSessionManager (org.keycloak.services.managers.AuthenticationSessionManager)4 EventBuilder (org.keycloak.events.EventBuilder)3 JWSInput (org.keycloak.jose.jws.JWSInput)3 JWSInputException (org.keycloak.jose.jws.JWSInputException)3