Search in sources :

Example 16 with VerificationException

use of org.keycloak.common.VerificationException in project keycloak by keycloak.

the class KeyPairVerifier method verify.

public static void verify(String privateKeyPem, String publicKeyPem) throws VerificationException {
    PrivateKey privateKey;
    try {
        privateKey = PemUtils.decodePrivateKey(privateKeyPem);
    } catch (Exception e) {
        throw new VerificationException("Failed to decode private key");
    }
    PublicKey publicKey;
    try {
        publicKey = PemUtils.decodePublicKey(publicKeyPem);
    } catch (Exception e) {
        throw new VerificationException("Failed to decode public key");
    }
    try {
        String jws = new JWSBuilder().content("content".getBytes()).rsa256(privateKey);
        if (!RSAProvider.verify(new JWSInput(jws), publicKey)) {
            throw new VerificationException("Keys don't match");
        }
    } catch (Exception e) {
        throw new VerificationException("Keys don't match");
    }
}
Also used : PrivateKey(java.security.PrivateKey) PublicKey(java.security.PublicKey) VerificationException(org.keycloak.common.VerificationException) JWSInput(org.keycloak.jose.jws.JWSInput) VerificationException(org.keycloak.common.VerificationException) JWSBuilder(org.keycloak.jose.jws.JWSBuilder)

Example 17 with VerificationException

use of org.keycloak.common.VerificationException in project keycloak by keycloak.

the class AsymmetricSignatureVerifierContext method verify.

@Override
public boolean verify(byte[] data, byte[] signature) throws VerificationException {
    try {
        Signature verifier = Signature.getInstance(JavaAlgorithm.getJavaAlgorithm(key.getAlgorithmOrDefault()));
        verifier.initVerify((PublicKey) key.getPublicKey());
        verifier.update(data);
        return verifier.verify(signature);
    } catch (Exception e) {
        throw new VerificationException("Signing failed", e);
    }
}
Also used : Signature(java.security.Signature) VerificationException(org.keycloak.common.VerificationException) VerificationException(org.keycloak.common.VerificationException)

Example 18 with VerificationException

use of org.keycloak.common.VerificationException 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 19 with VerificationException

use of org.keycloak.common.VerificationException in project keycloak by keycloak.

the class OAuthClient method verifyToken.

public <T extends JsonWebToken> T verifyToken(String token, Class<T> clazz) {
    try {
        TokenVerifier<T> verifier = TokenVerifier.create(token, clazz);
        String kid = verifier.getHeader().getKeyId();
        String algorithm = verifier.getHeader().getAlgorithm().name();
        KeyWrapper key = getRealmPublicKey(realm, algorithm, kid);
        AsymmetricSignatureVerifierContext verifierContext;
        switch(algorithm) {
            case Algorithm.ES256:
            case Algorithm.ES384:
            case Algorithm.ES512:
                verifierContext = new ServerECDSASignatureVerifierContext(key);
                break;
            default:
                verifierContext = new AsymmetricSignatureVerifierContext(key);
        }
        verifier.verifierContext(verifierContext);
        verifier.verify();
        return verifier.getToken();
    } catch (VerificationException e) {
        throw new RuntimeException("Failed to decode token", e);
    }
}
Also used : KeyWrapper(org.keycloak.crypto.KeyWrapper) AsymmetricSignatureVerifierContext(org.keycloak.crypto.AsymmetricSignatureVerifierContext) VerificationException(org.keycloak.common.VerificationException) ServerECDSASignatureVerifierContext(org.keycloak.crypto.ServerECDSASignatureVerifierContext)

Example 20 with VerificationException

use of org.keycloak.common.VerificationException in project keycloak by keycloak.

the class LoginActionsService method handleActionToken.

protected <T extends JsonWebToken & ActionTokenKeyModel> Response handleActionToken(String tokenString, String execution, String clientId, String tabId) {
    T token;
    ActionTokenHandler<T> handler;
    ActionTokenContext<T> tokenContext;
    String eventError = null;
    String defaultErrorMessage = null;
    AuthenticationSessionModel authSession = null;
    // Setup client, so error page will contain "back to application" link
    ClientModel client = null;
    if (clientId != null) {
        client = realm.getClientByClientId(clientId);
    }
    AuthenticationSessionManager authenticationSessionManager = new AuthenticationSessionManager(session);
    if (client != null) {
        session.getContext().setClient(client);
        authSession = authenticationSessionManager.getCurrentAuthenticationSession(realm, client, tabId);
    }
    event.event(EventType.EXECUTE_ACTION_TOKEN);
    // First resolve action token handler
    try {
        if (tokenString == null) {
            throw new ExplainedTokenVerificationException(null, Errors.NOT_ALLOWED, Messages.INVALID_REQUEST);
        }
        TokenVerifier<DefaultActionTokenKey> tokenVerifier = TokenVerifier.create(tokenString, DefaultActionTokenKey.class);
        DefaultActionTokenKey aToken = tokenVerifier.getToken();
        event.detail(Details.TOKEN_ID, aToken.getId()).detail(Details.ACTION, aToken.getActionId()).user(aToken.getUserId());
        handler = resolveActionTokenHandler(aToken.getActionId());
        eventError = handler.getDefaultEventError();
        defaultErrorMessage = handler.getDefaultErrorMessage();
        if (!realm.isEnabled()) {
            throw new ExplainedTokenVerificationException(aToken, Errors.REALM_DISABLED, Messages.REALM_NOT_ENABLED);
        }
        if (!checkSsl()) {
            throw new ExplainedTokenVerificationException(aToken, Errors.SSL_REQUIRED, Messages.HTTPS_REQUIRED);
        }
        TokenVerifier<DefaultActionTokenKey> verifier = tokenVerifier.withChecks(// Token introspection checks
        TokenVerifier.IS_ACTIVE, new TokenVerifier.RealmUrlCheck(Urls.realmIssuer(session.getContext().getUri().getBaseUri(), realm.getName())), ACTION_TOKEN_BASIC_CHECKS);
        String kid = verifier.getHeader().getKeyId();
        String algorithm = verifier.getHeader().getAlgorithm().name();
        SignatureVerifierContext signatureVerifier = session.getProvider(SignatureProvider.class, algorithm).verifier(kid);
        verifier.verifierContext(signatureVerifier);
        verifier.verify();
        token = TokenVerifier.create(tokenString, handler.getTokenClass()).getToken();
    } catch (TokenNotActiveException ex) {
        if (authSession != null) {
            event.clone().error(Errors.EXPIRED_CODE);
            String flowPath = authSession.getClientNote(AuthorizationEndpointBase.APP_INITIATED_FLOW);
            if (flowPath == null) {
                flowPath = AUTHENTICATE_PATH;
            }
            AuthenticationProcessor.resetFlow(authSession, flowPath);
            // Process correct flow
            return processFlowFromPath(flowPath, authSession, Messages.EXPIRED_ACTION_TOKEN_SESSION_EXISTS);
        }
        return handleActionTokenVerificationException(null, ex, Errors.EXPIRED_CODE, Messages.EXPIRED_ACTION_TOKEN_NO_SESSION);
    } catch (ExplainedTokenVerificationException ex) {
        return handleActionTokenVerificationException(null, ex, ex.getErrorEvent(), ex.getMessage());
    } catch (ExplainedVerificationException ex) {
        return handleActionTokenVerificationException(null, ex, ex.getErrorEvent(), ex.getMessage());
    } catch (VerificationException ex) {
        return handleActionTokenVerificationException(null, ex, eventError, defaultErrorMessage);
    }
    // Now proceed with the verification and handle the token
    tokenContext = new ActionTokenContext(session, realm, session.getContext().getUri(), clientConnection, request, event, handler, execution, this::processFlow, this::brokerLoginFlow);
    try {
        String tokenAuthSessionCompoundId = handler.getAuthenticationSessionIdFromToken(token, tokenContext, authSession);
        if (tokenAuthSessionCompoundId != null) {
            // This can happen if the token contains ID but user opens the link in a new browser
            String sessionId = AuthenticationSessionCompoundId.encoded(tokenAuthSessionCompoundId).getRootSessionId();
            LoginActionsServiceChecks.checkNotLoggedInYet(tokenContext, authSession, sessionId);
        }
        if (authSession == null) {
            authSession = handler.startFreshAuthenticationSession(token, tokenContext);
            tokenContext.setAuthenticationSession(authSession, true);
        } else if (tokenAuthSessionCompoundId == null || !LoginActionsServiceChecks.doesAuthenticationSessionFromCookieMatchOneFromToken(tokenContext, authSession, tokenAuthSessionCompoundId)) {
            // There exists an authentication session but no auth session ID was received in the action token
            logger.debugf("Authentication session in progress but no authentication session ID was found in action token %s, restarting.", token.getId());
            authenticationSessionManager.removeAuthenticationSession(realm, authSession, false);
            authSession = handler.startFreshAuthenticationSession(token, tokenContext);
            tokenContext.setAuthenticationSession(authSession, true);
            processLocaleParam(authSession);
        }
        initLoginEvent(authSession);
        event.event(handler.eventType());
        LoginActionsServiceChecks.checkIsUserValid(token, tokenContext);
        LoginActionsServiceChecks.checkIsClientValid(token, tokenContext);
        session.getContext().setClient(authSession.getClient());
        TokenVerifier.createWithoutSignature(token).withChecks(handler.getVerifiers(tokenContext)).verify();
        authSession = tokenContext.getAuthenticationSession();
        event = tokenContext.getEvent();
        event.event(handler.eventType());
        if (!handler.canUseTokenRepeatedly(token, tokenContext)) {
            LoginActionsServiceChecks.checkTokenWasNotUsedYet(token, tokenContext);
            authSession.setAuthNote(AuthenticationManager.INVALIDATE_ACTION_TOKEN, token.serializeKey());
        }
        authSession.setAuthNote(DefaultActionTokenKey.ACTION_TOKEN_USER_ID, token.getUserId());
        authSession.setAuthNote(Constants.KEY, tokenString);
        return handler.handleToken(token, tokenContext);
    } catch (ExplainedTokenVerificationException ex) {
        return handleActionTokenVerificationException(tokenContext, ex, ex.getErrorEvent(), ex.getMessage());
    } catch (LoginActionsServiceException ex) {
        Response response = ex.getResponse();
        return response == null ? handleActionTokenVerificationException(tokenContext, ex, eventError, defaultErrorMessage) : response;
    } catch (VerificationException ex) {
        return handleActionTokenVerificationException(tokenContext, ex, eventError, defaultErrorMessage);
    }
}
Also used : TokenNotActiveException(org.keycloak.exceptions.TokenNotActiveException) AuthenticationSessionModel(org.keycloak.sessions.AuthenticationSessionModel) RootAuthenticationSessionModel(org.keycloak.sessions.RootAuthenticationSessionModel) SignatureVerifierContext(org.keycloak.crypto.SignatureVerifierContext) ExplainedVerificationException(org.keycloak.authentication.ExplainedVerificationException) ActionTokenContext(org.keycloak.authentication.actiontoken.ActionTokenContext) DefaultActionTokenKey(org.keycloak.authentication.actiontoken.DefaultActionTokenKey) AuthenticationSessionManager(org.keycloak.services.managers.AuthenticationSessionManager) Response(javax.ws.rs.core.Response) ClientModel(org.keycloak.models.ClientModel) SignatureProvider(org.keycloak.crypto.SignatureProvider) GET(javax.ws.rs.GET) POST(javax.ws.rs.POST) ExplainedTokenVerificationException(org.keycloak.authentication.actiontoken.ExplainedTokenVerificationException) TokenVerifier(org.keycloak.TokenVerifier) VerificationException(org.keycloak.common.VerificationException) ExplainedVerificationException(org.keycloak.authentication.ExplainedVerificationException) ExplainedTokenVerificationException(org.keycloak.authentication.actiontoken.ExplainedTokenVerificationException)

Aggregations

VerificationException (org.keycloak.common.VerificationException)41 AccessToken (org.keycloak.representations.AccessToken)17 Test (org.junit.Test)8 JWSBuilder (org.keycloak.jose.jws.JWSBuilder)8 IOException (java.io.IOException)7 ClientModel (org.keycloak.models.ClientModel)7 SignatureProvider (org.keycloak.crypto.SignatureProvider)6 SignatureVerifierContext (org.keycloak.crypto.SignatureVerifierContext)6 UserSessionModel (org.keycloak.models.UserSessionModel)6 Response (javax.ws.rs.core.Response)4 OAuthErrorException (org.keycloak.OAuthErrorException)4 JWSInput (org.keycloak.jose.jws.JWSInput)4 UserModel (org.keycloak.models.UserModel)4 PublicKey (java.security.PublicKey)3 TokenVerifier (org.keycloak.TokenVerifier)3 AuthenticatedClientSessionModel (org.keycloak.models.AuthenticatedClientSessionModel)3 IDToken (org.keycloak.representations.IDToken)3 ConfigurationException (org.keycloak.saml.common.exceptions.ConfigurationException)3 ProcessingException (org.keycloak.saml.common.exceptions.ProcessingException)3 SAMLDocumentHolder (org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder)3