Search in sources :

Example 11 with VerificationException

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

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

the class AbstractSamlAuthenticationHandler method verifyRedirectBindingSignature.

private void verifyRedirectBindingSignature(String paramKey, KeyLocator keyLocator, String keyId) throws VerificationException {
    String request = facade.getRequest().getQueryParamValue(paramKey);
    String algorithm = facade.getRequest().getQueryParamValue(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY);
    String signature = facade.getRequest().getQueryParamValue(GeneralConstants.SAML_SIGNATURE_REQUEST_KEY);
    String decodedAlgorithm = facade.getRequest().getQueryParamValue(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY);
    if (request == null) {
        throw new VerificationException("SAML Request was null");
    }
    if (algorithm == null)
        throw new VerificationException("SigAlg was null");
    if (signature == null)
        throw new VerificationException("Signature was null");
    // Shibboleth doesn't sign the document for redirect binding.
    // todo maybe a flag?
    String relayState = facade.getRequest().getQueryParamValue(GeneralConstants.RELAY_STATE);
    KeycloakUriBuilder builder = KeycloakUriBuilder.fromPath("/").queryParam(paramKey, request);
    if (relayState != null) {
        builder.queryParam(GeneralConstants.RELAY_STATE, relayState);
    }
    builder.queryParam(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY, algorithm);
    String rawQuery = builder.build().getRawQuery();
    try {
        // byte[] decodedSignature = RedirectBindingUtil.urlBase64Decode(signature);
        byte[] decodedSignature = Base64.decode(signature);
        byte[] rawQueryBytes = rawQuery.getBytes("UTF-8");
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.getFromXmlMethod(decodedAlgorithm);
        if (!validateRedirectBindingSignature(signatureAlgorithm, rawQueryBytes, decodedSignature, keyLocator, keyId)) {
            throw new VerificationException("Invalid query param signature");
        }
    } catch (Exception e) {
        throw new VerificationException(e);
    }
}
Also used : KeycloakUriBuilder(org.keycloak.common.util.KeycloakUriBuilder) VerificationException(org.keycloak.common.VerificationException) SignatureAlgorithm(org.keycloak.saml.SignatureAlgorithm) VerificationException(org.keycloak.common.VerificationException) SignatureException(java.security.SignatureException) KeyManagementException(java.security.KeyManagementException) InvalidKeyException(java.security.InvalidKeyException) ProcessingException(org.keycloak.saml.common.exceptions.ProcessingException) ConfigurationException(org.keycloak.saml.common.exceptions.ConfigurationException) IOException(java.io.IOException)

Example 13 with VerificationException

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

the class SamlProtocolUtils method verifyRedirectSignature.

public static void verifyRedirectSignature(SAMLDocumentHolder documentHolder, KeyLocator locator, MultivaluedMap<String, String> encodedParams, String paramKey) throws VerificationException {
    String request = encodedParams.getFirst(paramKey);
    String algorithm = encodedParams.getFirst(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY);
    String signature = encodedParams.getFirst(GeneralConstants.SAML_SIGNATURE_REQUEST_KEY);
    String relayState = encodedParams.getFirst(GeneralConstants.RELAY_STATE);
    if (request == null)
        throw new VerificationException("SAM was null");
    if (algorithm == null)
        throw new VerificationException("SigAlg was null");
    if (signature == null)
        throw new VerificationException("Signature was null");
    String keyId = getMessageSigningKeyId(documentHolder.getSamlObject());
    // Shibboleth doesn't sign the document for redirect binding.
    // todo maybe a flag?
    StringBuilder rawQueryBuilder = new StringBuilder().append(paramKey).append("=").append(request);
    if (encodedParams.containsKey(GeneralConstants.RELAY_STATE)) {
        rawQueryBuilder.append("&" + GeneralConstants.RELAY_STATE + "=").append(relayState);
    }
    rawQueryBuilder.append("&" + GeneralConstants.SAML_SIG_ALG_REQUEST_KEY + "=").append(algorithm);
    String rawQuery = rawQueryBuilder.toString();
    try {
        byte[] decodedSignature = RedirectBindingUtil.urlBase64Decode(signature);
        String decodedAlgorithm = RedirectBindingUtil.urlDecode(encodedParams.getFirst(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY));
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.getFromXmlMethod(decodedAlgorithm);
        // todo plugin signature alg
        Signature validator = signatureAlgorithm.createSignature();
        Key key = locator.getKey(keyId);
        if (key instanceof PublicKey) {
            validator.initVerify((PublicKey) key);
            validator.update(rawQuery.getBytes("UTF-8"));
        } else {
            throw new VerificationException("Invalid key locator for signature verification");
        }
        if (!validator.verify(decodedSignature)) {
            throw new VerificationException("Invalid query param signature");
        }
    } catch (Exception e) {
        throw new VerificationException(e);
    }
}
Also used : PublicKey(java.security.PublicKey) Signature(java.security.Signature) SAML2Signature(org.keycloak.saml.processing.api.saml.v2.sig.SAML2Signature) VerificationException(org.keycloak.common.VerificationException) SignatureAlgorithm(org.keycloak.saml.SignatureAlgorithm) PublicKey(java.security.PublicKey) Key(java.security.Key) ProcessingException(org.keycloak.saml.common.exceptions.ProcessingException) ConfigurationException(org.keycloak.saml.common.exceptions.ConfigurationException) VerificationException(org.keycloak.common.VerificationException) CertificateException(java.security.cert.CertificateException) ParsingException(org.keycloak.saml.common.exceptions.ParsingException)

Example 14 with VerificationException

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

the class SamlService method artifactResolve.

/**
 * Takes an artifact resolve message and returns the artifact response, if the artifact is found belonging to a session
 * of the issuer.
 * @param artifactResolveMessage The artifact resolve message sent by the client
 * @param artifactResolveHolder the document containing the artifact resolve message sent by the client
 * @return a Response containing the SOAP message with the ArifactResponse
 * @throws ParsingException
 * @throws ConfigurationException
 * @throws ProcessingException
 */
public Response artifactResolve(ArtifactResolveType artifactResolveMessage, SAMLDocumentHolder artifactResolveHolder) throws ParsingException, ConfigurationException, ProcessingException {
    logger.debug("Received artifactResolve message for artifact " + artifactResolveMessage.getArtifact() + "\n" + "Message: \n" + DocumentUtil.getDocumentAsString(artifactResolveHolder.getSamlDocument()));
    // Artifact from resolve request
    String artifact = artifactResolveMessage.getArtifact();
    if (artifact == null) {
        logger.errorf("Artifact to resolve was null");
        return emptyArtifactResponseMessage(artifactResolveMessage, null, JBossSAMLURIConstants.STATUS_REQUEST_DENIED.getUri());
    }
    ArtifactResolver artifactResolver = getArtifactResolver(artifact);
    if (artifactResolver == null) {
        logger.errorf("Cannot find ArtifactResolver for artifact %s", artifact);
        return emptyArtifactResponseMessage(artifactResolveMessage, null, JBossSAMLURIConstants.STATUS_REQUEST_DENIED.getUri());
    }
    // Obtain details of session that issued artifact and check if it corresponds to issuer of Resolve message
    SamlArtifactSessionMappingModel sessionMapping = getArtifactSessionMappingStore().get(artifact);
    if (sessionMapping == null) {
        logger.errorf("No data stored for artifact %s", artifact);
        return emptyArtifactResponseMessage(artifactResolveMessage, null);
    }
    UserSessionModel userSessionModel = session.sessions().getUserSession(realm, sessionMapping.getUserSessionId());
    if (userSessionModel == null) {
        logger.errorf("UserSession with id: %s, that corresponds to artifact: %s does not exist.", sessionMapping.getUserSessionId(), artifact);
        return emptyArtifactResponseMessage(artifactResolveMessage, null);
    }
    AuthenticatedClientSessionModel clientSessionModel = userSessionModel.getAuthenticatedClientSessions().get(sessionMapping.getClientSessionId());
    if (clientSessionModel == null) {
        logger.errorf("ClientSession with id: %s, that corresponds to artifact: %s and UserSession: %s does not exist.", sessionMapping.getClientSessionId(), artifact, sessionMapping.getUserSessionId());
        return emptyArtifactResponseMessage(artifactResolveMessage, null);
    }
    ClientModel clientModel = getAndCheckClientModel(sessionMapping.getClientSessionId(), artifactResolveMessage.getIssuer().getValue());
    SamlClient samlClient = new SamlClient(clientModel);
    // Check signature within ArtifactResolve request if client requires it
    if (samlClient.requiresClientSignature()) {
        try {
            SamlProtocolUtils.verifyDocumentSignature(clientModel, artifactResolveHolder.getSamlDocument());
        } catch (VerificationException e) {
            SamlService.logger.error("request validation failed", e);
            return emptyArtifactResponseMessage(artifactResolveMessage, clientModel);
        }
    }
    // Obtain artifactResponse from clientSessionModel
    String artifactResponseString;
    try {
        artifactResponseString = artifactResolver.resolveArtifact(clientSessionModel, artifact);
    } catch (ArtifactResolverProcessingException e) {
        logger.errorf(e, "Failed to resolve artifact: %s.", artifact);
        return emptyArtifactResponseMessage(artifactResolveMessage, clientModel);
    }
    // Artifact is successfully resolved, we can remove session mapping from storage
    getArtifactSessionMappingStore().remove(artifact);
    Document artifactResponseDocument = null;
    ArtifactResponseType artifactResponseType = null;
    try {
        SAMLDataMarshaller marshaller = new SAMLDataMarshaller();
        artifactResponseType = marshaller.deserialize(artifactResponseString, ArtifactResponseType.class);
        artifactResponseDocument = SamlProtocolUtils.convert(artifactResponseType);
    } catch (ParsingException | ConfigurationException | ProcessingException e) {
        logger.errorf(e, "Failed to obtain document from ArtifactResponseString: %s.", artifactResponseString);
        return emptyArtifactResponseMessage(artifactResolveMessage, clientModel);
    }
    // If clientSession is in LOGGING_OUT action, now we can move it to LOGGED_OUT
    if (CommonClientSessionModel.Action.LOGGING_OUT.name().equals(clientSessionModel.getAction())) {
        clientSessionModel.setAction(CommonClientSessionModel.Action.LOGGED_OUT.name());
        // If Keycloak sent LogoutResponse we need to also remove UserSession
        if (artifactResponseType.getAny() instanceof StatusResponseType && artifactResponseString.contains(JBossSAMLConstants.LOGOUT_RESPONSE.get())) {
            if (!UserSessionModel.State.LOGGED_OUT_UNCONFIRMED.equals(userSessionModel.getState())) {
                logger.warnf("Keycloak issued LogoutResponse for clientSession %s, however user session %s was not in LOGGED_OUT_UNCONFIRMED state.", clientSessionModel.getId(), userSessionModel.getId());
            }
            AuthenticationManager.finishUnconfirmedUserSession(session, realm, userSessionModel);
        }
    }
    return artifactResponseMessage(artifactResolveMessage, artifactResponseDocument, clientModel);
}
Also used : UserSessionModel(org.keycloak.models.UserSessionModel) AuthenticatedClientSessionModel(org.keycloak.models.AuthenticatedClientSessionModel) Document(org.w3c.dom.Document) SAMLDataMarshaller(org.keycloak.broker.saml.SAMLDataMarshaller) StatusResponseType(org.keycloak.dom.saml.v2.protocol.StatusResponseType) SamlArtifactSessionMappingModel(org.keycloak.models.SamlArtifactSessionMappingModel) ClientModel(org.keycloak.models.ClientModel) ConfigurationException(org.keycloak.saml.common.exceptions.ConfigurationException) ParserConfigurationException(javax.xml.parsers.ParserConfigurationException) ParsingException(org.keycloak.saml.common.exceptions.ParsingException) VerificationException(org.keycloak.common.VerificationException) ArtifactResponseType(org.keycloak.dom.saml.v2.protocol.ArtifactResponseType) ProcessingException(org.keycloak.saml.common.exceptions.ProcessingException)

Example 15 with VerificationException

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

the class OpenShiftTokenReviewEndpoint method tokenReview.

@Path("/{client_id}")
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response tokenReview(@PathParam("client_id") String clientId, OpenShiftTokenReviewRequestRepresentation reviewRequest) throws Exception {
    event.event(EventType.INTROSPECT_TOKEN);
    if (clientId != null) {
        session.setAttribute("client_id", clientId);
    }
    checkSsl();
    checkRealm();
    authorizeClient();
    RealmModel realm = session.getContext().getRealm();
    AccessToken token = null;
    try {
        TokenVerifier<AccessToken> verifier = TokenVerifier.create(reviewRequest.getSpec().getToken(), AccessToken.class).realmUrl(Urls.realmIssuer(session.getContext().getUri().getBaseUri(), realm.getName())).audience(reviewRequest.getSpec().getAudiences());
        SignatureVerifierContext verifierContext = session.getProvider(SignatureProvider.class, verifier.getHeader().getAlgorithm().name()).verifier(verifier.getHeader().getKeyId());
        verifier.verifierContext(verifierContext);
        verifier.verify();
        token = verifier.getToken();
    } catch (VerificationException e) {
        error(401, Errors.INVALID_TOKEN, "Token verification failure");
    }
    if (!tokenManager.checkTokenValidForIntrospection(session, realm, token, true)) {
        error(401, Errors.INVALID_TOKEN, "Token verification failure");
    }
    OpenShiftTokenReviewResponseRepresentation response = new OpenShiftTokenReviewResponseRepresentation();
    response.getStatus().setAuthenticated(true);
    response.getStatus().setUser(new OpenShiftTokenReviewResponseRepresentation.User());
    OpenShiftTokenReviewResponseRepresentation.User userRep = response.getStatus().getUser();
    userRep.setUid(token.getSubject());
    userRep.setUsername(token.getPreferredUsername());
    if (token.getScope() != null && !token.getScope().isEmpty()) {
        OpenShiftTokenReviewResponseRepresentation.Extra extra = new OpenShiftTokenReviewResponseRepresentation.Extra();
        extra.setScopes(token.getScope().split(" "));
        userRep.setExtra(extra);
    }
    if (token.getOtherClaims() != null && token.getOtherClaims().get("groups") != null) {
        List<String> groups = (List<String>) token.getOtherClaims().get("groups");
        userRep.setGroups(groups);
    }
    event.success();
    return Response.ok(response, MediaType.APPLICATION_JSON).build();
}
Also used : SignatureVerifierContext(org.keycloak.crypto.SignatureVerifierContext) RealmModel(org.keycloak.models.RealmModel) SignatureProvider(org.keycloak.crypto.SignatureProvider) AccessToken(org.keycloak.representations.AccessToken) VerificationException(org.keycloak.common.VerificationException) List(java.util.List) Path(javax.ws.rs.Path) POST(javax.ws.rs.POST) Consumes(javax.ws.rs.Consumes) Produces(javax.ws.rs.Produces)

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