Search in sources :

Example 1 with ProcessingException

use of org.keycloak.saml.common.exceptions.ProcessingException in project keycloak by keycloak.

the class XMLEncryptionUtil method encryptElement.

/**
 * <p>
 * Encrypts an element in a XML document using the specified public key, secret key, and key size. This method
 * doesn't wrap
 * the encrypted element in a new element. Instead, it replaces the element with its encrypted version.
 * </p>
 * <p>
 * For example, calling this method to encrypt the <tt><b>inner</b></tt> element in the following XML document
 *
 * <pre>
 *    &lt;root&gt;
 *       &lt;outer&gt;
 *          &lt;inner&gt;
 *             ...
 *          &lt;/inner&gt;
 *       &lt;/outer&gt;
 *    &lt;/root&gt;
 * </pre>
 *
 * would result in a document similar to
 *
 * <pre>
 *    &lt;root&gt;
 *       &lt;outer&gt;
 *          &lt;xenc:EncryptedData xmlns:xenc="..."&gt;
 *             ...
 *          &lt;/xenc:EncryptedData&gt;
 *       &lt;/outer&gt;
 *    &lt;/root&gt;
 * </pre>
 *
 * </p>
 *
 * @param document the {@code Document} that contains the element to be encrypted.
 * @param element the {@code Element} to be encrypted.
 * @param publicKey the {@code PublicKey} that must be used to encrypt the secret key.
 * @param secretKey the {@code SecretKey} used to encrypt the specified element.
 * @param keySize the size (in bits) of the secret key.
 *
 * @throws ProcessingException if an error occurs while encrypting the element with the specified params.
 */
public static void encryptElement(Document document, Element element, PublicKey publicKey, SecretKey secretKey, int keySize) throws ProcessingException {
    if (element == null)
        throw logger.nullArgumentError("element");
    if (document == null)
        throw logger.nullArgumentError("document");
    XMLCipher cipher = null;
    EncryptedKey encryptedKey = encryptKey(document, secretKey, publicKey, keySize);
    String encryptionAlgorithm = getXMLEncryptionURL(secretKey.getAlgorithm(), keySize);
    // Encrypt the Document
    try {
        cipher = XMLCipher.getInstance(encryptionAlgorithm);
        cipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
    } catch (XMLEncryptionException e1) {
        throw logger.processingError(e1);
    }
    Document encryptedDoc;
    try {
        encryptedDoc = cipher.doFinal(document, element);
    } catch (Exception e) {
        throw logger.processingError(e);
    }
    // The EncryptedKey element is added
    Element encryptedKeyElement = cipher.martial(document, encryptedKey);
    // Outer ds:KeyInfo Element to hold the EncryptionKey
    Element sigElement = encryptedDoc.createElementNS(XMLSignature.XMLNS, DS_KEY_INFO);
    sigElement.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns:ds", XMLSignature.XMLNS);
    sigElement.appendChild(encryptedKeyElement);
    // Insert the Encrypted key before the CipherData element
    NodeList nodeList = encryptedDoc.getElementsByTagNameNS(EncryptionConstants.EncryptionSpecNS, EncryptionConstants._TAG_CIPHERDATA);
    if (nodeList == null || nodeList.getLength() == 0)
        throw logger.domMissingElementError("xenc:CipherData");
    Element cipherDataElement = (Element) nodeList.item(0);
    Node cipherParent = cipherDataElement.getParentNode();
    cipherParent.insertBefore(sigElement, cipherDataElement);
}
Also used : EncryptedKey(org.apache.xml.security.encryption.EncryptedKey) Element(org.w3c.dom.Element) NodeList(org.w3c.dom.NodeList) Node(org.w3c.dom.Node) XMLCipher(org.apache.xml.security.encryption.XMLCipher) Document(org.w3c.dom.Document) ProcessingException(org.keycloak.saml.common.exceptions.ProcessingException) XMLEncryptionException(org.apache.xml.security.encryption.XMLEncryptionException) ConfigurationException(org.keycloak.saml.common.exceptions.ConfigurationException) XMLEncryptionException(org.apache.xml.security.encryption.XMLEncryptionException)

Example 2 with ProcessingException

use of org.keycloak.saml.common.exceptions.ProcessingException 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 ProcessingException

use of org.keycloak.saml.common.exceptions.ProcessingException in project keycloak by keycloak.

the class SamlProtocol method frontchannelLogout.

@Override
public Response frontchannelLogout(UserSessionModel userSession, AuthenticatedClientSessionModel clientSession) {
    ClientModel client = clientSession.getClient();
    SamlClient samlClient = new SamlClient(client);
    try {
        boolean postBinding = isLogoutPostBindingForClient(clientSession);
        String bindingUri = getLogoutServiceUrl(session, client, postBinding ? SAML_POST_BINDING : SAML_REDIRECT_BINDING, false);
        if (bindingUri == null) {
            logger.warnf("Failed to logout client %s, skipping this client.  Please configure the logout service url in the admin console for your client applications.", client.getClientId());
            return null;
        }
        NodeGenerator[] extensions = new NodeGenerator[] {};
        if (!postBinding) {
            if (samlClient.requiresRealmSignature() && samlClient.addExtensionsElementWithKeyInfo()) {
                KeyManager.ActiveRsaKey keys = session.keys().getActiveRsaKey(realm);
                String keyName = samlClient.getXmlSigKeyInfoKeyNameTransformer().getKeyName(keys.getKid(), keys.getCertificate());
                extensions = new NodeGenerator[] { new KeycloakKeySamlExtensionGenerator(keyName) };
            }
        }
        LogoutRequestType logoutRequest = createLogoutRequest(bindingUri, clientSession, client, extensions);
        JaxrsSAML2BindingBuilder binding = createBindingBuilder(samlClient, "true".equals(clientSession.getNote(JBossSAMLURIConstants.SAML_HTTP_ARTIFACT_BINDING.get())));
        // If this session uses artifact binding, send an artifact instead of the LogoutRequest
        if ("true".equals(clientSession.getNote(JBossSAMLURIConstants.SAML_HTTP_ARTIFACT_BINDING.get())) && useArtifactForLogout(client)) {
            clientSession.setAction(CommonClientSessionModel.Action.LOGGING_OUT.name());
            return buildArtifactAuthenticatedResponse(clientSession, bindingUri, logoutRequest, binding);
        }
        Document samlDocument = SAML2Request.convert(logoutRequest);
        if (postBinding) {
            // This is POST binding, hence KeyID is included in dsig:KeyInfo/dsig:KeyName, no need to add <samlp:Extensions> element
            return binding.postBinding(samlDocument).request(bindingUri);
        } else {
            logger.debug("frontchannel redirect binding");
            return binding.redirectBinding(samlDocument).request(bindingUri);
        }
    } catch (ConfigurationException | ProcessingException | IOException | ParsingException e) {
        throw new RuntimeException(e);
    }
}
Also used : LogoutRequestType(org.keycloak.dom.saml.v2.protocol.LogoutRequestType) IOException(java.io.IOException) KeycloakKeySamlExtensionGenerator(org.keycloak.saml.processing.core.util.KeycloakKeySamlExtensionGenerator) Document(org.w3c.dom.Document) ClientModel(org.keycloak.models.ClientModel) ConfigurationException(org.keycloak.saml.common.exceptions.ConfigurationException) ParsingException(org.keycloak.saml.common.exceptions.ParsingException) KeyManager(org.keycloak.models.KeyManager) NodeGenerator(org.keycloak.saml.SamlProtocolExtensionsAwareBuilder.NodeGenerator) ProcessingException(org.keycloak.saml.common.exceptions.ProcessingException)

Example 4 with ProcessingException

use of org.keycloak.saml.common.exceptions.ProcessingException in project keycloak by keycloak.

the class SamlProtocol method buildLogoutArtifactResponse.

/**
 * This method, instead of sending the actual response with the token, sends
 * the artifact message via post or redirect. This method is only to be used for the final LogoutResponse.
 *
 * @param userSession    The current user session being logged out
 * @param redirectUri    the redirect uri to the client
 * @param statusResponseType   a Document containing the saml Response
 * @param bindingBuilder the current JaxrsSAML2BindingBuilder configured with information for signing and encryption
 * @return A response (POSTed form or redirect) with a newly generated artifact
 * @throws ProcessingException
 * @throws IOException
 */
protected Response buildLogoutArtifactResponse(UserSessionModel userSession, String redirectUri, StatusResponseType statusResponseType, JaxrsSAML2BindingBuilder bindingBuilder) throws ProcessingException, ConfigurationException {
    try {
        String artifact = buildArtifactAndStoreResponse(statusResponseType, userSession);
        String relayState = userSession.getNote(SAML_LOGOUT_RELAY_STATE);
        logger.debugf("Sending artifact for LogoutResponse %s to user %s", artifact, userSession.getLoginUsername());
        if (isLogoutPostBindingForInitiator(userSession)) {
            return artifactPost(redirectUri, artifact, relayState, bindingBuilder);
        } else {
            return artifactRedirect(redirectUri, artifact, relayState);
        }
    } catch (ArtifactResolverProcessingException e) {
        throw new ProcessingException(e);
    }
}
Also used : ProcessingException(org.keycloak.saml.common.exceptions.ProcessingException)

Example 5 with ProcessingException

use of org.keycloak.saml.common.exceptions.ProcessingException in project keycloak by keycloak.

the class SamlService method emptyArtifactResponseMessage.

private Response emptyArtifactResponseMessage(ArtifactResolveType artifactResolveMessage, ClientModel clientModel, URI responseStatusCode) throws ProcessingException, ConfigurationException {
    ArtifactResponseType artifactResponse = SamlProtocolUtils.buildArtifactResponse(null, SAML2NameIDBuilder.value(RealmsResource.realmBaseUrl(session.getContext().getUri()).build(realm.getName()).toString()).build(), responseStatusCode);
    Document artifactResponseDocument;
    try {
        artifactResponseDocument = SamlProtocolUtils.convert(artifactResponse);
    } catch (ParsingException | ConfigurationException | ProcessingException e) {
        logger.errorf("Failed to obtain document from ArtifactResponse: %s.", artifactResponse);
        throw new ProcessingException(Errors.INVALID_SAML_ARTIFACT_RESPONSE, e);
    }
    return artifactResponseMessage(artifactResolveMessage, artifactResponseDocument, clientModel);
}
Also used : ConfigurationException(org.keycloak.saml.common.exceptions.ConfigurationException) ParserConfigurationException(javax.xml.parsers.ParserConfigurationException) ParsingException(org.keycloak.saml.common.exceptions.ParsingException) ArtifactResponseType(org.keycloak.dom.saml.v2.protocol.ArtifactResponseType) Document(org.w3c.dom.Document) ProcessingException(org.keycloak.saml.common.exceptions.ProcessingException)

Aggregations

ProcessingException (org.keycloak.saml.common.exceptions.ProcessingException)40 ConfigurationException (org.keycloak.saml.common.exceptions.ConfigurationException)25 Document (org.w3c.dom.Document)16 ParsingException (org.keycloak.saml.common.exceptions.ParsingException)15 Element (org.w3c.dom.Element)12 IOException (java.io.IOException)8 AuthnRequestType (org.keycloak.dom.saml.v2.protocol.AuthnRequestType)8 ResponseType (org.keycloak.dom.saml.v2.protocol.ResponseType)8 QName (javax.xml.namespace.QName)7 SAMLDocumentHolder (org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder)5 ParserConfigurationException (javax.xml.parsers.ParserConfigurationException)4 StatusResponseType (org.keycloak.dom.saml.v2.protocol.StatusResponseType)4 SAML2Request (org.keycloak.saml.processing.api.saml.v2.request.SAML2Request)4 BigInteger (java.math.BigInteger)3 KeyFactory (java.security.KeyFactory)3 Response (javax.ws.rs.core.Response)3 EncryptedKey (org.apache.xml.security.encryption.EncryptedKey)3 XMLCipher (org.apache.xml.security.encryption.XMLCipher)3 XMLEncryptionException (org.apache.xml.security.encryption.XMLEncryptionException)3 AttributeType (org.keycloak.dom.saml.v2.assertion.AttributeType)3