Search in sources :

Example 26 with VerificationException

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

the class CookieTokenStore method getPrincipalFromCookie.

public static KeycloakPrincipal<RefreshableKeycloakSecurityContext> getPrincipalFromCookie(KeycloakDeployment deployment, HttpFacade facade, AdapterTokenStore tokenStore) {
    OIDCHttpFacade.Cookie cookie = facade.getRequest().getCookie(AdapterConstants.KEYCLOAK_ADAPTER_STATE_COOKIE);
    if (cookie == null) {
        log.debug("Not found adapter state cookie in current request");
        return null;
    }
    String cookieVal = cookie.getValue();
    String[] tokens = cookieVal.split(DELIM);
    if (tokens.length != 3) {
        log.warnf("Invalid format of %s cookie. Count of tokens: %s, expected 3", AdapterConstants.KEYCLOAK_ADAPTER_STATE_COOKIE, tokens.length);
        return null;
    }
    String accessTokenString = tokens[0];
    String idTokenString = tokens[1];
    String refreshTokenString = tokens[2];
    try {
        // Skip check if token is active now. It's supposed to be done later by the caller
        TokenVerifier<AccessToken> tokenVerifier = AdapterTokenVerifier.createVerifier(accessTokenString, deployment, true, AccessToken.class).checkActive(false).verify();
        AccessToken accessToken = tokenVerifier.getToken();
        IDToken idToken;
        if (idTokenString != null && idTokenString.length() > 0) {
            try {
                JWSInput input = new JWSInput(idTokenString);
                idToken = input.readJsonContent(IDToken.class);
            } catch (JWSInputException e) {
                throw new VerificationException(e);
            }
        } else {
            idToken = null;
        }
        log.debug("Token Verification succeeded!");
        RefreshableKeycloakSecurityContext secContext = new RefreshableKeycloakSecurityContext(deployment, tokenStore, accessTokenString, accessToken, idTokenString, idToken, refreshTokenString);
        return new KeycloakPrincipal<>(AdapterUtils.getPrincipalName(deployment, accessToken), secContext);
    } catch (VerificationException ve) {
        log.warn("Failed verify token", ve);
        return null;
    }
}
Also used : AccessToken(org.keycloak.representations.AccessToken) JWSInputException(org.keycloak.jose.jws.JWSInputException) VerificationException(org.keycloak.common.VerificationException) IDToken(org.keycloak.representations.IDToken) JWSInput(org.keycloak.jose.jws.JWSInput) KeycloakPrincipal(org.keycloak.KeycloakPrincipal)

Example 27 with VerificationException

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

the class RefreshableKeycloakSecurityContext method refreshExpiredToken.

/**
 * @param checkActive if true, then we won't send refresh request if current accessToken is still active.
 * @return true if accessToken is active or was successfully refreshed
 */
public boolean refreshExpiredToken(boolean checkActive) {
    if (checkActive) {
        if (log.isTraceEnabled()) {
            log.trace("checking whether to refresh.");
        }
        if (isActive() && isTokenTimeToLiveSufficient(this.token))
            return true;
    }
    // Might be serialized in HttpSession?
    if (this.deployment == null || refreshToken == null)
        return false;
    if (!this.getRealm().equals(this.deployment.getRealm())) {
        // this should not happen, but let's check it anyway
        return false;
    }
    if (log.isTraceEnabled()) {
        log.trace("Doing refresh");
    }
    // 
    synchronized (this) {
        if (checkActive) {
            log.trace("Checking whether token has been refreshed in another thread already.");
            if (isActive() && isTokenTimeToLiveSufficient(this.token))
                return true;
        }
        AccessTokenResponse response;
        try {
            response = ServerRequest.invokeRefresh(deployment, refreshToken);
        } catch (IOException e) {
            log.error("Refresh token failure", e);
            return false;
        } catch (ServerRequest.HttpFailure httpFailure) {
            final Logger.Level logLevel = httpFailure.getError().contains("Refresh token expired") ? Logger.Level.WARN : Logger.Level.ERROR;
            log.log(logLevel, "Refresh token failure status: " + httpFailure.getStatus() + " " + httpFailure.getError());
            return false;
        }
        if (log.isTraceEnabled()) {
            log.trace("received refresh response");
        }
        String tokenString = response.getToken();
        AccessToken token = null;
        IDToken idToken = null;
        try {
            AdapterTokenVerifier.VerifiedTokens tokens = AdapterTokenVerifier.verifyTokens(tokenString, response.getIdToken(), deployment);
            token = tokens.getAccessToken();
            idToken = tokens.getIdToken();
            log.debug("Token Verification succeeded!");
        } catch (VerificationException e) {
            log.error("failed verification of token");
            return false;
        }
        // If the TTL is greater-or-equal to the expire time on the refreshed token, have to abort or go into an infinite refresh loop
        if (!isTokenTimeToLiveSufficient(token)) {
            log.error("failed to refresh the token with a longer time-to-live than the minimum");
            return false;
        }
        if (response.getNotBeforePolicy() > deployment.getNotBefore()) {
            deployment.updateNotBefore(response.getNotBeforePolicy());
        }
        if (idToken != null) {
            this.idToken = idToken;
            this.idTokenString = response.getIdToken();
        }
        this.token = token;
        if (response.getRefreshToken() != null) {
            if (log.isTraceEnabled()) {
                log.trace("Setup new refresh token to the security context");
            }
            this.refreshToken = response.getRefreshToken();
        }
        this.tokenString = tokenString;
        if (tokenStore != null) {
            tokenStore.refreshCallback(this);
        }
    }
    return true;
}
Also used : AdapterTokenVerifier(org.keycloak.adapters.rotation.AdapterTokenVerifier) AccessToken(org.keycloak.representations.AccessToken) VerificationException(org.keycloak.common.VerificationException) IDToken(org.keycloak.representations.IDToken) IOException(java.io.IOException) AccessTokenResponse(org.keycloak.representations.AccessTokenResponse)

Example 28 with VerificationException

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

the class AbstractSamlAuthenticationHandler method handleSamlResponse.

protected AuthOutcome handleSamlResponse(String samlResponse, String relayState, OnSessionCreated onCreateSession) {
    SAMLDocumentHolder holder = null;
    boolean postBinding = false;
    String requestUri = facade.getRequest().getURI();
    if (facade.getRequest().getMethod().equalsIgnoreCase("GET")) {
        int index = requestUri.indexOf('?');
        if (index > -1) {
            requestUri = requestUri.substring(0, index);
        }
        holder = extractRedirectBindingResponse(samlResponse);
    } else {
        postBinding = true;
        holder = extractPostBindingResponse(samlResponse);
    }
    if (holder == null) {
        log.error("Error parsing SAML document");
        return failed(CHALLENGE_EXTRACTION_FAILURE);
    }
    final StatusResponseType statusResponse = (StatusResponseType) holder.getSamlObject();
    // validate destination
    if (statusResponse.getDestination() == null && containsUnencryptedSignature(holder, postBinding)) {
        log.error("Destination field required.");
        return failed(CHALLENGE_EXTRACTION_FAILURE);
    }
    if (!destinationValidator.validate(requestUri, statusResponse.getDestination())) {
        log.error("Request URI '" + requestUri + "' does not match SAML request destination '" + statusResponse.getDestination() + "'");
        return failedTerminal();
    }
    if (statusResponse instanceof ResponseType) {
        try {
            if (deployment.getIDP().getSingleSignOnService().validateResponseSignature()) {
                try {
                    validateSamlSignature(holder, postBinding, GeneralConstants.SAML_RESPONSE_KEY);
                } catch (VerificationException e) {
                    log.error("Failed to verify saml response signature", e);
                    return failed(CHALLENGE_INVALID_SIGNATURE);
                }
            }
            return handleLoginResponse(holder, postBinding, onCreateSession);
        } finally {
            sessionStore.setCurrentAction(SamlSessionStore.CurrentAction.NONE);
        }
    } else {
        if (sessionStore.isLoggingOut()) {
            try {
                if (deployment.getIDP().getSingleLogoutService().validateResponseSignature()) {
                    try {
                        validateSamlSignature(holder, postBinding, GeneralConstants.SAML_RESPONSE_KEY);
                    } catch (VerificationException e) {
                        log.error("Failed to verify saml response signature", e);
                        return failedTerminal();
                    }
                }
                return handleLogoutResponse(holder, statusResponse, relayState);
            } finally {
                sessionStore.setCurrentAction(SamlSessionStore.CurrentAction.NONE);
            }
        } else if (sessionStore.isLoggingIn()) {
            try {
                // KEYCLOAK-2107 - handle user not authenticated due passive mode. Return special outcome so different authentication mechanisms can behave accordingly.
                StatusType status = statusResponse.getStatus();
                if (checkStatusCodeValue(status.getStatusCode(), JBossSAMLURIConstants.STATUS_RESPONDER.get()) && checkStatusCodeValue(status.getStatusCode().getStatusCode(), JBossSAMLURIConstants.STATUS_NO_PASSIVE.get())) {
                    log.debug("Not authenticated due passive mode Status found in SAML response: " + status.toString());
                    return AuthOutcome.NOT_AUTHENTICATED;
                }
                return failed(createAuthChallenge403(statusResponse));
            } finally {
                sessionStore.setCurrentAction(SamlSessionStore.CurrentAction.NONE);
            }
        }
        log.warn("Keycloak Adapter obtained Response, that is not understood. This may be because the containers " + "cookies are not properly configured with SameSite settings. Refer to KEYCLOAK-14103 for more details.");
        return AuthOutcome.NOT_ATTEMPTED;
    }
}
Also used : SAMLDocumentHolder(org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder) StatusType(org.keycloak.dom.saml.v2.protocol.StatusType) VerificationException(org.keycloak.common.VerificationException) StatusResponseType(org.keycloak.dom.saml.v2.protocol.StatusResponseType) ResponseType(org.keycloak.dom.saml.v2.protocol.ResponseType) StatusResponseType(org.keycloak.dom.saml.v2.protocol.StatusResponseType)

Example 29 with VerificationException

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

the class AbstractSamlAuthenticationHandler method handleSamlRequest.

protected AuthOutcome handleSamlRequest(String samlRequest, String relayState) {
    SAMLDocumentHolder holder = null;
    boolean postBinding = false;
    String requestUri = facade.getRequest().getURI();
    if (facade.getRequest().getMethod().equalsIgnoreCase("GET")) {
        // strip out query params
        int index = requestUri.indexOf('?');
        if (index > -1) {
            requestUri = requestUri.substring(0, index);
        }
        holder = SAMLRequestParser.parseRequestRedirectBinding(samlRequest);
    } else {
        postBinding = true;
        holder = SAMLRequestParser.parseRequestPostBinding(samlRequest);
    }
    if (holder == null) {
        log.error("Error parsing SAML document");
        return failedTerminal();
    }
    RequestAbstractType requestAbstractType = (RequestAbstractType) holder.getSamlObject();
    if (requestAbstractType.getDestination() == null && containsUnencryptedSignature(holder, postBinding)) {
        log.error("Destination field required.");
        return failed(CHALLENGE_EXTRACTION_FAILURE);
    }
    if (!destinationValidator.validate(requestUri, requestAbstractType.getDestination())) {
        log.error("Expected destination '" + requestUri + "' got '" + requestAbstractType.getDestination() + "'");
        return failedTerminal();
    }
    if (requestAbstractType instanceof LogoutRequestType) {
        if (deployment.getIDP().getSingleLogoutService().validateRequestSignature()) {
            try {
                validateSamlSignature(holder, postBinding, GeneralConstants.SAML_REQUEST_KEY);
            } catch (VerificationException e) {
                log.error("Failed to verify saml request signature", e);
                return failedTerminal();
            }
        }
        LogoutRequestType logout = (LogoutRequestType) requestAbstractType;
        return logoutRequest(logout, relayState);
    } else {
        log.error("unknown SAML request type");
        return failedTerminal();
    }
}
Also used : SAMLDocumentHolder(org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder) RequestAbstractType(org.keycloak.dom.saml.v2.protocol.RequestAbstractType) LogoutRequestType(org.keycloak.dom.saml.v2.protocol.LogoutRequestType) VerificationException(org.keycloak.common.VerificationException)

Example 30 with VerificationException

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

the class MacSignatureVerifierContext method verify.

@Override
public boolean verify(byte[] data, byte[] signature) throws VerificationException {
    try {
        Mac mac = Mac.getInstance(JavaAlgorithm.getJavaAlgorithm(key.getAlgorithmOrDefault()));
        mac.init(key.getSecretKey());
        mac.update(data);
        byte[] verificationSignature = mac.doFinal();
        return MessageDigest.isEqual(verificationSignature, signature);
    } catch (Exception e) {
        throw new VerificationException("Signing failed", e);
    }
}
Also used : VerificationException(org.keycloak.common.VerificationException) Mac(javax.crypto.Mac) VerificationException(org.keycloak.common.VerificationException)

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