Search in sources :

Example 1 with OAuthErrorException

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

the class KeycloakInstalled method loginDesktop.

public void loginDesktop() throws IOException, VerificationException, OAuthErrorException, URISyntaxException, ServerRequest.HttpFailure, InterruptedException {
    callback = new CallbackListener();
    callback.start();
    String redirectUri = getRedirectUri(callback);
    String state = UUID.randomUUID().toString();
    Pkce pkce = deployment.isPkce() ? generatePkce() : null;
    String authUrl = createAuthUrl(redirectUri, state, pkce);
    desktopProvider.browse(new URI(authUrl));
    try {
        callback.await();
    } catch (InterruptedException e) {
        callback.stop();
        throw e;
    }
    if (callback.error != null) {
        throw new OAuthErrorException(callback.error, callback.errorDescription);
    }
    if (!state.equals(callback.state)) {
        throw new VerificationException("Invalid state");
    }
    processCode(callback.code, redirectUri, pkce);
    status = Status.LOGGED_DESKTOP;
}
Also used : OAuthErrorException(org.keycloak.OAuthErrorException) VerificationException(org.keycloak.common.VerificationException) URI(java.net.URI)

Example 2 with OAuthErrorException

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

the class TokenManager method validateTokenReuseForRefresh.

private void validateTokenReuseForRefresh(KeycloakSession session, RealmModel realm, RefreshToken refreshToken, TokenValidation validation) throws OAuthErrorException {
    if (realm.isRevokeRefreshToken()) {
        AuthenticatedClientSessionModel clientSession = validation.clientSessionCtx.getClientSession();
        try {
            validateTokenReuse(session, realm, refreshToken, clientSession, true);
            int currentCount = clientSession.getCurrentRefreshTokenUseCount();
            clientSession.setCurrentRefreshTokenUseCount(currentCount + 1);
        } catch (OAuthErrorException oee) {
            if (logger.isDebugEnabled()) {
                logger.debugf("Failed validation of refresh token %s due it was used before. Realm: %s, client: %s, user: %s, user session: %s. Will detach client session from user session", refreshToken.getId(), realm.getName(), clientSession.getClient().getClientId(), clientSession.getUserSession().getUser().getUsername(), clientSession.getUserSession().getId());
            }
            clientSession.detachFromUserSession();
            throw oee;
        }
    }
}
Also used : OAuthErrorException(org.keycloak.OAuthErrorException) AuthenticatedClientSessionModel(org.keycloak.models.AuthenticatedClientSessionModel)

Example 3 with OAuthErrorException

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

the class TokenManager method validateTokenReuseForIntrospection.

private boolean validateTokenReuseForIntrospection(KeycloakSession session, RealmModel realm, AccessToken token) {
    UserSessionModel userSession = null;
    if (token.getType().equals(TokenUtil.TOKEN_TYPE_REFRESH)) {
        userSession = session.sessions().getUserSession(realm, token.getSessionState());
    } else {
        UserSessionManager sessionManager = new UserSessionManager(session);
        userSession = sessionManager.findOfflineUserSession(realm, token.getSessionState());
    }
    ClientModel client = realm.getClientByClientId(token.getIssuedFor());
    AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
    try {
        validateTokenReuse(session, realm, token, clientSession, false);
        return true;
    } catch (OAuthErrorException e) {
        return false;
    }
}
Also used : UserSessionManager(org.keycloak.services.managers.UserSessionManager) ClientModel(org.keycloak.models.ClientModel) UserSessionModel(org.keycloak.models.UserSessionModel) OAuthErrorException(org.keycloak.OAuthErrorException) AuthenticatedClientSessionModel(org.keycloak.models.AuthenticatedClientSessionModel)

Example 4 with OAuthErrorException

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

the class TokenManager method validateToken.

public TokenValidation validateToken(KeycloakSession session, UriInfo uriInfo, ClientConnection connection, RealmModel realm, RefreshToken oldToken, HttpHeaders headers) throws OAuthErrorException {
    UserSessionModel userSession = null;
    boolean offline = TokenUtil.TOKEN_TYPE_OFFLINE.equals(oldToken.getType());
    if (offline) {
        UserSessionManager sessionManager = new UserSessionManager(session);
        userSession = sessionManager.findOfflineUserSession(realm, oldToken.getSessionState());
        if (userSession != null) {
            // Revoke timeouted offline userSession
            if (!AuthenticationManager.isOfflineSessionValid(realm, userSession)) {
                sessionManager.revokeOfflineUserSession(userSession);
                throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Offline session not active", "Offline session not active");
            }
        } else {
            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Offline user session not found", "Offline user session not found");
        }
    } else {
        // Find userSession regularly for online tokens
        userSession = session.sessions().getUserSession(realm, oldToken.getSessionState());
        if (!AuthenticationManager.isSessionValid(realm, userSession)) {
            AuthenticationManager.backchannelLogout(session, realm, userSession, uriInfo, connection, headers, true);
            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Session not active", "Session not active");
        }
    }
    UserModel user = userSession.getUser();
    if (user == null) {
        throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Invalid refresh token", "Unknown user");
    }
    if (!user.isEnabled()) {
        throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "User disabled", "User disabled");
    }
    if (oldToken.isIssuedBeforeSessionStart(userSession.getStarted())) {
        logger.debug("Refresh toked issued before the user session started");
        throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Refresh toked issued before the user session started");
    }
    ClientModel client = session.getContext().getClient();
    AuthenticatedClientSessionModel clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
    // Can theoretically happen in cross-dc environment. Try to see if userSession with our client is available in remoteCache
    if (clientSession == null) {
        userSession = new UserSessionCrossDCManager(session).getUserSessionWithClient(realm, userSession.getId(), offline, client.getId());
        if (userSession != null) {
            clientSession = userSession.getAuthenticatedClientSessionByClient(client.getId());
        } else {
            throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Session doesn't have required client", "Session doesn't have required client");
        }
    }
    if (oldToken.isIssuedBeforeSessionStart(clientSession.getStarted())) {
        logger.debug("Refresh toked issued before the client session started");
        throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Refresh toked issued before the client session started");
    }
    if (!client.getClientId().equals(oldToken.getIssuedFor())) {
        throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Unmatching clients", "Unmatching clients");
    }
    try {
        TokenVerifier.createWithoutSignature(oldToken).withChecks(NotBeforeCheck.forModel(client), NotBeforeCheck.forModel(session, realm, user)).verify();
    } catch (VerificationException e) {
        throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale token");
    }
    // Setup clientScopes from refresh token to the context
    String oldTokenScope = oldToken.getScope();
    // Case when offline token is migrated from previous version
    if (oldTokenScope == null && userSession.isOffline()) {
        logger.debugf("Migrating offline token of user '%s' for client '%s' of realm '%s'", user.getUsername(), client.getClientId(), realm.getName());
        MigrationUtils.migrateOldOfflineToken(session, realm, client, user);
        oldTokenScope = OAuth2Constants.OFFLINE_ACCESS;
    }
    ClientSessionContext clientSessionCtx = DefaultClientSessionContext.fromClientSessionAndScopeParameter(clientSession, oldTokenScope, session);
    // Check user didn't revoke granted consent
    if (!verifyConsentStillAvailable(session, user, client, clientSessionCtx.getClientScopesStream())) {
        throw new OAuthErrorException(OAuthErrorException.INVALID_SCOPE, "Client no longer has requested consent from user");
    }
    clientSessionCtx.setAttribute(OIDCLoginProtocol.NONCE_PARAM, oldToken.getNonce());
    // recreate token.
    AccessToken newToken = createClientAccessToken(session, realm, client, user, userSession, clientSessionCtx);
    return new TokenValidation(user, userSession, clientSessionCtx, newToken);
}
Also used : UserSessionModel(org.keycloak.models.UserSessionModel) OAuthErrorException(org.keycloak.OAuthErrorException) AuthenticatedClientSessionModel(org.keycloak.models.AuthenticatedClientSessionModel) UserSessionCrossDCManager(org.keycloak.services.managers.UserSessionCrossDCManager) UserSessionManager(org.keycloak.services.managers.UserSessionManager) UserModel(org.keycloak.models.UserModel) ClientModel(org.keycloak.models.ClientModel) DefaultClientSessionContext(org.keycloak.services.util.DefaultClientSessionContext) ClientSessionContext(org.keycloak.models.ClientSessionContext) AccessToken(org.keycloak.representations.AccessToken) VerificationException(org.keycloak.common.VerificationException)

Example 5 with OAuthErrorException

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

the class LogoutEndpoint method logoutToken.

/**
 * Logout a session via a non-browser invocation.  Similar signature to refresh token except there is no grant_type.
 * You must pass in the refresh token and
 * authenticate the client if it is not public.
 *
 * If the client is a confidential client
 * you must include the client-id and secret in an Basic Auth Authorization header.
 *
 * If the client is a public client, then you must include a "client_id" form parameter.
 *
 * returns 204 if successful, 400 if not with a json error response.
 *
 * @return
 */
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response logoutToken() {
    cors = Cors.add(request).auth().allowedMethods("POST").auth().exposedHeaders(Cors.ACCESS_CONTROL_ALLOW_METHODS);
    MultivaluedMap<String, String> form = request.getDecodedFormParameters();
    checkSsl();
    event.event(EventType.LOGOUT);
    ClientModel client = authorizeClient();
    String refreshToken = form.getFirst(OAuth2Constants.REFRESH_TOKEN);
    if (refreshToken == null) {
        event.error(Errors.INVALID_TOKEN);
        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "No refresh token", Response.Status.BAD_REQUEST);
    }
    try {
        session.clientPolicy().triggerOnEvent(new LogoutRequestContext(form));
    } catch (ClientPolicyException cpe) {
        throw new CorsErrorResponseException(cors, cpe.getError(), cpe.getErrorDetail(), cpe.getErrorStatus());
    }
    RefreshToken token = null;
    try {
        // KEYCLOAK-6771 Certificate Bound Token
        token = tokenManager.verifyRefreshToken(session, realm, client, request, refreshToken, false);
        boolean offline = TokenUtil.TOKEN_TYPE_OFFLINE.equals(token.getType());
        UserSessionModel userSessionModel;
        if (offline) {
            UserSessionManager sessionManager = new UserSessionManager(session);
            userSessionModel = sessionManager.findOfflineUserSession(realm, token.getSessionState());
        } else {
            userSessionModel = session.sessions().getUserSession(realm, token.getSessionState());
        }
        if (userSessionModel != null) {
            checkTokenIssuedAt(token, userSessionModel);
            logout(userSessionModel, offline);
        }
    } catch (OAuthErrorException 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);
        }
    }
    return cors.builder(Response.noContent()).build();
}
Also used : UserSessionManager(org.keycloak.services.managers.UserSessionManager) ClientModel(org.keycloak.models.ClientModel) UserSessionModel(org.keycloak.models.UserSessionModel) RefreshToken(org.keycloak.representations.RefreshToken) OAuthErrorException(org.keycloak.OAuthErrorException) CorsErrorResponseException(org.keycloak.services.CorsErrorResponseException) LogoutRequestContext(org.keycloak.services.clientpolicy.context.LogoutRequestContext) ClientPolicyException(org.keycloak.services.clientpolicy.ClientPolicyException) POST(javax.ws.rs.POST) Consumes(javax.ws.rs.Consumes)

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