Search in sources :

Example 6 with OAuthErrorException

use of org.keycloak.OAuthErrorException in project keycloak by keycloak.

the class LogoutEndpoint method logout.

/**
 * Logout user session.  User must be logged in via a session cookie.
 *
 * When the logout is initiated by a remote idp, the parameter "initiating_idp" can be supplied. This param will
 * prevent upstream logout (since the logout procedure has already been started in the remote idp).
 *
 * @param redirectUri
 * @param initiatingIdp The alias of the idp initiating the logout.
 * @return
 */
@GET
@NoCache
public // deprecated
Response logout(// deprecated
@QueryParam(OIDCLoginProtocol.REDIRECT_URI_PARAM) String redirectUri, @QueryParam("id_token_hint") String encodedIdToken, @QueryParam("post_logout_redirect_uri") String postLogoutRedirectUri, @QueryParam("state") String state, @QueryParam("initiating_idp") String initiatingIdp) {
    String redirect = postLogoutRedirectUri != null ? postLogoutRedirectUri : redirectUri;
    IDToken idToken = null;
    if (encodedIdToken != null) {
        try {
            idToken = tokenManager.verifyIDTokenSignature(session, encodedIdToken);
            TokenVerifier.createWithoutSignature(idToken).tokenType(TokenUtil.TOKEN_TYPE_ID).verify();
        } catch (OAuthErrorException | VerificationException e) {
            event.event(EventType.LOGOUT);
            event.error(Errors.INVALID_TOKEN);
            return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.SESSION_NOT_ACTIVE);
        }
    }
    if (redirect != null) {
        String validatedUri;
        ClientModel client = (idToken == null || idToken.getIssuedFor() == null) ? null : realm.getClientByClientId(idToken.getIssuedFor());
        if (client != null) {
            validatedUri = RedirectUtils.verifyRedirectUri(session, redirect, client);
        } else {
            validatedUri = RedirectUtils.verifyRealmRedirectUri(session, redirect);
        }
        if (validatedUri == null) {
            event.event(EventType.LOGOUT);
            event.detail(Details.REDIRECT_URI, redirect);
            event.error(Errors.INVALID_REDIRECT_URI);
            return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.INVALID_REDIRECT_URI);
        }
        redirect = validatedUri;
    }
    UserSessionModel userSession = null;
    if (idToken != null) {
        try {
            userSession = session.sessions().getUserSession(realm, idToken.getSessionState());
            if (userSession != null) {
                checkTokenIssuedAt(idToken, userSession);
            }
        } catch (OAuthErrorException e) {
            event.event(EventType.LOGOUT);
            event.error(Errors.INVALID_TOKEN);
            return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.SESSION_NOT_ACTIVE);
        }
    }
    // authenticate identity cookie, but ignore an access token timeout as we're logging out anyways.
    AuthenticationManager.AuthResult authResult = AuthenticationManager.authenticateIdentityCookie(session, realm, false);
    if (authResult != null) {
        userSession = userSession != null ? userSession : authResult.getSession();
        return initiateBrowserLogout(userSession, redirect, state, initiatingIdp);
    } else if (userSession != null) {
        // identity cookie is missing but there's valid id_token_hint which matches session cookie => continue with browser logout
        if (idToken != null && idToken.getSessionState().equals(AuthenticationManager.getSessionIdFromSessionCookie(session))) {
            return initiateBrowserLogout(userSession, redirect, state, initiatingIdp);
        }
        // this might happen when a backChannelLogout is already initiated from AuthenticationManager.authenticateIdentityCookie
        if (userSession.getState() != LOGGING_OUT && userSession.getState() != LOGGED_OUT) {
            // non browser logout
            event.event(EventType.LOGOUT);
            AuthenticationManager.backchannelLogout(session, realm, userSession, session.getContext().getUri(), clientConnection, headers, true);
            event.user(userSession.getUser()).session(userSession).success();
        }
    }
    if (redirect != null) {
        UriBuilder uriBuilder = UriBuilder.fromUri(redirect);
        if (state != null)
            uriBuilder.queryParam(OIDCLoginProtocol.STATE_PARAM, state);
        return Response.status(302).location(uriBuilder.build()).build();
    } else {
        // TODO Empty content with ok makes no sense. Should it display a page? Or use noContent?
        session.getProvider(SecurityHeadersProvider.class).options().allowEmptyContentType();
        return Response.ok().build();
    }
}
Also used : AuthenticationManager(org.keycloak.services.managers.AuthenticationManager) ClientModel(org.keycloak.models.ClientModel) UserSessionModel(org.keycloak.models.UserSessionModel) OAuthErrorException(org.keycloak.OAuthErrorException) VerificationException(org.keycloak.common.VerificationException) IDToken(org.keycloak.representations.IDToken) UriBuilder(javax.ws.rs.core.UriBuilder) GET(javax.ws.rs.GET) NoCache(org.jboss.resteasy.annotations.cache.NoCache)

Example 7 with OAuthErrorException

use of org.keycloak.OAuthErrorException in project keycloak by keycloak.

the class TokenEndpoint method refreshTokenGrant.

public Response refreshTokenGrant() {
    String refreshToken = formParams.getFirst(OAuth2Constants.REFRESH_TOKEN);
    if (refreshToken == null) {
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "No refresh token", Response.Status.BAD_REQUEST);
    }
    try {
        session.clientPolicy().triggerOnEvent(new TokenRefreshContext(formParams));
    } catch (ClientPolicyException cpe) {
        event.error(cpe.getError());
        throw new CorsErrorResponseException(cors, cpe.getError(), cpe.getErrorDetail(), cpe.getErrorStatus());
    }
    AccessTokenResponse res;
    try {
        // KEYCLOAK-6771 Certificate Bound Token
        TokenManager.RefreshResult result = tokenManager.refreshAccessToken(session, session.getContext().getUri(), clientConnection, realm, client, refreshToken, event, headers, request);
        res = result.getResponse();
        if (!result.isOfflineToken()) {
            UserSessionModel userSession = session.sessions().getUserSession(realm, res.getSessionState());
            AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
            updateClientSession(clientSession);
            updateUserSessionFromClientAuth(userSession);
        }
    } catch (OAuthErrorException e) {
        logger.trace(e.getMessage(), e);
        // KEYCLOAK-6771 Certificate Bound Token
        if (MtlsHoKTokenUtil.CERT_VERIFY_ERROR_DESC.equals(e.getDescription())) {
            event.error(Errors.NOT_ALLOWED);
            throw new CorsErrorResponseException(cors, e.getError(), e.getDescription(), Response.Status.UNAUTHORIZED);
        } else {
            event.error(Errors.INVALID_TOKEN);
            throw new CorsErrorResponseException(cors, e.getError(), e.getDescription(), Response.Status.BAD_REQUEST);
        }
    }
    event.success();
    return cors.builder(Response.ok(res, MediaType.APPLICATION_JSON_TYPE)).build();
}
Also used : UserSessionModel(org.keycloak.models.UserSessionModel) OAuthErrorException(org.keycloak.OAuthErrorException) TokenRefreshContext(org.keycloak.services.clientpolicy.context.TokenRefreshContext) AuthenticatedClientSessionModel(org.keycloak.models.AuthenticatedClientSessionModel) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException) TokenManager(org.keycloak.protocol.oidc.TokenManager) AccessTokenResponse(org.keycloak.representations.AccessTokenResponse) ClientPolicyException(org.keycloak.services.clientpolicy.ClientPolicyException)

Example 8 with OAuthErrorException

use of org.keycloak.OAuthErrorException in project keycloak by keycloak.

the class TokenManager method refreshAccessToken.

public RefreshResult refreshAccessToken(KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm, ClientModel authorizedClient, String encodedRefreshToken, EventBuilder event, HttpHeaders headers, HttpRequest request) throws OAuthErrorException {
    RefreshToken refreshToken = verifyRefreshToken(session, realm, authorizedClient, request, encodedRefreshToken, true);
    event.user(refreshToken.getSubject()).session(refreshToken.getSessionState()).detail(Details.REFRESH_TOKEN_ID, refreshToken.getId()).detail(Details.REFRESH_TOKEN_TYPE, refreshToken.getType());
    TokenValidation validation = validateToken(session, uriInfo, connection, realm, refreshToken, headers);
    AuthenticatedClientSessionModel clientSession = validation.clientSessionCtx.getClientSession();
    // validate authorizedClient is same as validated client
    if (!clientSession.getClient().getId().equals(authorizedClient.getId())) {
        throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token. Token client and authorized client don't match");
    }
    validateTokenReuseForRefresh(session, realm, refreshToken, validation);
    int currentTime = Time.currentTime();
    clientSession.setTimestamp(currentTime);
    validation.userSession.setLastSessionRefresh(currentTime);
    if (refreshToken.getAuthorization() != null) {
        validation.newToken.setAuthorization(refreshToken.getAuthorization());
    }
    AccessTokenResponseBuilder responseBuilder = responseBuilder(realm, authorizedClient, event, session, validation.userSession, validation.clientSessionCtx).accessToken(validation.newToken);
    if (OIDCAdvancedConfigWrapper.fromClientModel(authorizedClient).isUseRefreshToken()) {
        responseBuilder.generateRefreshToken();
    }
    if (validation.newToken.getAuthorization() != null && OIDCAdvancedConfigWrapper.fromClientModel(authorizedClient).isUseRefreshToken()) {
        responseBuilder.getRefreshToken().setAuthorization(validation.newToken.getAuthorization());
    }
    // KEYCLOAK-6771 Certificate Bound Token
    // https://tools.ietf.org/html/draft-ietf-oauth-mtls-08#section-3.1
    // bind refreshed access and refresh token with Client Certificate
    AccessToken.CertConf certConf = refreshToken.getCertConf();
    if (certConf != null) {
        responseBuilder.getAccessToken().setCertConf(certConf);
        if (OIDCAdvancedConfigWrapper.fromClientModel(authorizedClient).isUseRefreshToken()) {
            responseBuilder.getRefreshToken().setCertConf(certConf);
        }
    }
    String scopeParam = clientSession.getNote(OAuth2Constants.SCOPE);
    if (TokenUtil.isOIDCRequest(scopeParam)) {
        responseBuilder.generateIDToken().generateAccessTokenHash();
    }
    AccessTokenResponse res = responseBuilder.build();
    return new RefreshResult(res, TokenUtil.TOKEN_TYPE_OFFLINE.equals(refreshToken.getType()));
}
Also used : RefreshToken(org.keycloak.representations.RefreshToken) OAuthErrorException(org.keycloak.OAuthErrorException) AccessToken(org.keycloak.representations.AccessToken) AuthenticatedClientSessionModel(org.keycloak.models.AuthenticatedClientSessionModel) AccessTokenResponse(org.keycloak.representations.AccessTokenResponse)

Aggregations

OAuthErrorException (org.keycloak.OAuthErrorException)8 AuthenticatedClientSessionModel (org.keycloak.models.AuthenticatedClientSessionModel)5 UserSessionModel (org.keycloak.models.UserSessionModel)5 ClientModel (org.keycloak.models.ClientModel)4 VerificationException (org.keycloak.common.VerificationException)3 UserSessionManager (org.keycloak.services.managers.UserSessionManager)3 AccessToken (org.keycloak.representations.AccessToken)2 AccessTokenResponse (org.keycloak.representations.AccessTokenResponse)2 RefreshToken (org.keycloak.representations.RefreshToken)2 CorsErrorResponseException (org.keycloak.services.CorsErrorResponseException)2 ClientPolicyException (org.keycloak.services.clientpolicy.ClientPolicyException)2 URI (java.net.URI)1 Consumes (javax.ws.rs.Consumes)1 GET (javax.ws.rs.GET)1 POST (javax.ws.rs.POST)1 UriBuilder (javax.ws.rs.core.UriBuilder)1 NoCache (org.jboss.resteasy.annotations.cache.NoCache)1 ClientSessionContext (org.keycloak.models.ClientSessionContext)1 UserModel (org.keycloak.models.UserModel)1 TokenManager (org.keycloak.protocol.oidc.TokenManager)1