Search in sources :

Example 1 with SignatureAlgorithm

use of org.keycloak.saml.SignatureAlgorithm 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 2 with SignatureAlgorithm

use of org.keycloak.saml.SignatureAlgorithm in project keycloak by keycloak.

the class SamlProtocol method finishLogout.

@Override
public Response finishLogout(UserSessionModel userSession) {
    logger.debug("finishLogout");
    String logoutBindingUri = userSession.getNote(SAML_LOGOUT_BINDING_URI);
    if (logoutBindingUri == null) {
        logger.error("Can't finish SAML logout as there is no logout binding set.  Please configure the logout service url in the admin console for your client applications.");
        return ErrorPage.error(session, null, Response.Status.BAD_REQUEST, Messages.FAILED_LOGOUT);
    }
    String logoutRelayState = userSession.getNote(SAML_LOGOUT_RELAY_STATE);
    SAML2LogoutResponseBuilder builder = new SAML2LogoutResponseBuilder();
    builder.logoutRequestID(userSession.getNote(SAML_LOGOUT_REQUEST_ID));
    builder.destination(logoutBindingUri);
    builder.issuer(getResponseIssuer(realm));
    JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder(session);
    binding.relayState(logoutRelayState);
    String signingAlgorithm = userSession.getNote(SAML_LOGOUT_SIGNATURE_ALGORITHM);
    boolean postBinding = isLogoutPostBindingForInitiator(userSession);
    if (signingAlgorithm != null) {
        SignatureAlgorithm algorithm = SignatureAlgorithm.valueOf(signingAlgorithm);
        String canonicalization = userSession.getNote(SAML_LOGOUT_CANONICALIZATION);
        if (canonicalization != null) {
            binding.canonicalizationMethod(canonicalization);
        }
        KeyManager.ActiveRsaKey keys = session.keys().getActiveRsaKey(realm);
        XmlKeyInfoKeyNameTransformer transformer = XmlKeyInfoKeyNameTransformer.from(userSession.getNote(SAML_SERVER_SIGNATURE_KEYINFO_KEY_NAME_TRANSFORMER), SamlClient.DEFAULT_XML_KEY_INFO_KEY_NAME_TRANSFORMER);
        String keyName = transformer.getKeyName(keys.getKid(), keys.getCertificate());
        binding.signatureAlgorithm(algorithm).signWith(keyName, keys.getPrivateKey(), keys.getPublicKey(), keys.getCertificate()).signDocument();
        boolean addExtension = (!postBinding) && Objects.equals("true", userSession.getNote(SamlProtocol.SAML_LOGOUT_ADD_EXTENSIONS_ELEMENT_WITH_KEY_INFO));
        if (addExtension) {
            // Only include extension if REDIRECT binding and signing whole SAML protocol message
            builder.addExtension(new KeycloakKeySamlExtensionGenerator(keyName));
        }
    }
    Response response;
    try {
        response = buildLogoutResponse(userSession, logoutBindingUri, builder, binding);
    } catch (ConfigurationException | ProcessingException | IOException e) {
        throw new RuntimeException(e);
    }
    if (logoutBindingUri != null) {
        event.detail(Details.REDIRECT_URI, logoutBindingUri);
    }
    event.event(EventType.LOGOUT).detail(Details.AUTH_METHOD, userSession.getAuthMethod()).client(session.getContext().getClient()).user(userSession.getUser()).session(userSession).detail(Details.USERNAME, userSession.getLoginUsername()).detail(Details.RESPONSE_MODE, postBinding ? SamlProtocol.SAML_POST_BINDING : SamlProtocol.SAML_REDIRECT_BINDING).detail(SamlProtocol.SAML_LOGOUT_REQUEST_ID, userSession.getNote(SAML_LOGOUT_REQUEST_ID)).success();
    return response;
}
Also used : SAML2LogoutResponseBuilder(org.keycloak.saml.SAML2LogoutResponseBuilder) XmlKeyInfoKeyNameTransformer(org.keycloak.saml.common.util.XmlKeyInfoKeyNameTransformer) SignatureAlgorithm(org.keycloak.saml.SignatureAlgorithm) IOException(java.io.IOException) KeycloakKeySamlExtensionGenerator(org.keycloak.saml.processing.core.util.KeycloakKeySamlExtensionGenerator) Response(javax.ws.rs.core.Response) CloseableHttpResponse(org.apache.http.client.methods.CloseableHttpResponse) ConfigurationException(org.keycloak.saml.common.exceptions.ConfigurationException) KeyManager(org.keycloak.models.KeyManager) ProcessingException(org.keycloak.saml.common.exceptions.ProcessingException)

Example 3 with SignatureAlgorithm

use of org.keycloak.saml.SignatureAlgorithm 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 4 with SignatureAlgorithm

use of org.keycloak.saml.SignatureAlgorithm in project keycloak by keycloak.

the class BasicSamlTest method testSpecialCharsInRelayState.

private void testSpecialCharsInRelayState(String encodedRelayState) throws Exception {
    AuthnRequestType loginRep = SamlClient.createLoginRequestDocument(SAML_CLIENT_ID_SALES_POST_SIG, SAML_ASSERTION_CONSUMER_URL_SALES_POST_SIG, getAuthServerSamlEndpoint(REALM_NAME));
    Document doc = SAML2Request.convert(loginRep);
    URI redirect = Binding.REDIRECT.createSamlUnsignedRequest(getAuthServerSamlEndpoint(REALM_NAME), null, doc).getURI();
    String query = redirect.getRawQuery();
    SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.RSA_SHA256;
    // now add the relayState
    String relayStatePart = encodedRelayState == null ? "" : ("&" + GeneralConstants.RELAY_STATE + "=" + encodedRelayState);
    String sigAlgPart = "&" + GeneralConstants.SAML_SIG_ALG_REQUEST_KEY + "=" + Encode.encodeQueryParamAsIs(signatureAlgorithm.getXmlSignatureMethod());
    Signature signature = signatureAlgorithm.createSignature();
    byte[] sig;
    signature.initSign(KeyUtils.privateKeyFromString(SAML_CLIENT_SALES_POST_SIG_PRIVATE_KEY));
    signature.update(query.getBytes(GeneralConstants.SAML_CHARSET));
    signature.update(relayStatePart.getBytes(GeneralConstants.SAML_CHARSET));
    signature.update(sigAlgPart.getBytes(GeneralConstants.SAML_CHARSET));
    sig = signature.sign();
    String encodedSig = RedirectBindingUtil.base64Encode(sig);
    String sigPart = "&" + GeneralConstants.SAML_SIGNATURE_REQUEST_KEY + "=" + Encode.encodeQueryParamAsIs(encodedSig);
    new SamlClientBuilder().navigateTo(redirect.toString() + relayStatePart + sigAlgPart + sigPart).assertResponse(statusCodeIsHC(Status.OK)).execute();
}
Also used : AuthnRequestType(org.keycloak.dom.saml.v2.protocol.AuthnRequestType) SamlClientBuilder(org.keycloak.testsuite.util.SamlClientBuilder) Signature(java.security.Signature) SignatureAlgorithm(org.keycloak.saml.SignatureAlgorithm) Matchers.containsString(org.hamcrest.Matchers.containsString) IOUtil.documentToString(org.keycloak.testsuite.utils.io.IOUtil.documentToString) Document(org.w3c.dom.Document) URI(java.net.URI) PROTOCOL_NSURI(org.keycloak.saml.common.constants.JBossSAMLURIConstants.PROTOCOL_NSURI)

Aggregations

SignatureAlgorithm (org.keycloak.saml.SignatureAlgorithm)4 ConfigurationException (org.keycloak.saml.common.exceptions.ConfigurationException)3 ProcessingException (org.keycloak.saml.common.exceptions.ProcessingException)3 IOException (java.io.IOException)2 Signature (java.security.Signature)2 VerificationException (org.keycloak.common.VerificationException)2 URI (java.net.URI)1 InvalidKeyException (java.security.InvalidKeyException)1 Key (java.security.Key)1 KeyManagementException (java.security.KeyManagementException)1 PublicKey (java.security.PublicKey)1 SignatureException (java.security.SignatureException)1 CertificateException (java.security.cert.CertificateException)1 Response (javax.ws.rs.core.Response)1 CloseableHttpResponse (org.apache.http.client.methods.CloseableHttpResponse)1 Matchers.containsString (org.hamcrest.Matchers.containsString)1 KeycloakUriBuilder (org.keycloak.common.util.KeycloakUriBuilder)1 AuthnRequestType (org.keycloak.dom.saml.v2.protocol.AuthnRequestType)1 KeyManager (org.keycloak.models.KeyManager)1 SAML2LogoutResponseBuilder (org.keycloak.saml.SAML2LogoutResponseBuilder)1