All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.pac4j.saml.metadata.DefaultSAML2MetadataSigner Maven / Gradle / Ivy

package org.pac4j.saml.metadata;

import org.opensaml.xmlsec.SignatureSigningParameters;
import org.opensaml.xmlsec.signature.SignableXMLObject;
import org.opensaml.xmlsec.signature.support.SignatureConstants;
import org.opensaml.xmlsec.signature.support.SignatureSupport;
import org.pac4j.saml.config.SAML2Configuration;
import org.pac4j.saml.crypto.CredentialProvider;
import org.pac4j.saml.exceptions.SAMLException;
import org.pac4j.saml.util.Configuration;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.Objects;
import java.util.Optional;

/**
 * This is {@link DefaultSAML2MetadataSigner}.
 *
 * @author Misagh Moayyed
 * @since 5.0.0
 */
public class DefaultSAML2MetadataSigner implements SAML2MetadataSigner {
    protected final CredentialProvider credentialProvider;

    protected final String signatureAlgorithm;

    protected final String signatureReferenceDigestMethod;

    protected final SAML2Configuration configuration;

    public DefaultSAML2MetadataSigner(final SAML2Configuration configuration) {
        this.configuration = configuration;
        this.credentialProvider = null;
        this.signatureAlgorithm = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
        this.signatureReferenceDigestMethod = "http://www.w3.org/2001/04/xmlenc#sha256";
    }

    public DefaultSAML2MetadataSigner(final CredentialProvider credentialProvider,
                                      final String signatureAlgorithm,
                                      final String signatureReferenceDigestMethod) {
        this.configuration = null;
        this.credentialProvider = credentialProvider;
        this.signatureAlgorithm = signatureAlgorithm;
        this.signatureReferenceDigestMethod = signatureReferenceDigestMethod;
    }
    private byte[] sign(final byte[] metadata) throws Exception {
        try (var is = new ByteArrayInputStream(metadata)) {
            final var document = Configuration.getParserPool().parse(is);
            final var documentElement = document.getDocumentElement();
            final var unmarshaller = Configuration.getUnmarshallerFactory().getUnmarshaller(documentElement);
            final var xmlObject = Objects.requireNonNull(unmarshaller).unmarshall(documentElement);
            if (xmlObject instanceof SignableXMLObject root && !root.isSigned()) {
                sign(root);
                try (var writer = Configuration.serializeSamlObject(root)) {
                    return writer.toString().getBytes(StandardCharsets.UTF_8);
                }
            }
            return metadata;
        }
    }

    @Override
    public String sign(final String metadata) {
        try {
            var input = metadata.getBytes(StandardCharsets.UTF_8);
            var result = sign(input);
            return new String(result, StandardCharsets.UTF_8);
        } catch (final Exception e) {
            throw new SAMLException(e.getMessage(), e);
        }
    }

    @Override
    public void sign(final File metadataFile) {
        try {
            var input = Files.readAllBytes(metadataFile.toPath());
            var result = sign(input);
            Files.writeString(metadataFile.toPath(), new String(result, StandardCharsets.UTF_8));
        } catch (final Exception e) {
            throw new SAMLException(e.getMessage(), e);
        }
    }

    @Override
    public void sign(final SignableXMLObject descriptor) {
        try {
            final var signingParameters = new SignatureSigningParameters();

            final var activeProvider = Objects.requireNonNull(Optional.ofNullable(configuration)
                .map(SAML2Configuration::getCredentialProvider)
                .orElse(this.credentialProvider));
            signingParameters.setKeyInfoGenerator(activeProvider.getKeyInfoGenerator());
            signingParameters.setSigningCredential(activeProvider.getCredential());

            final var signingAlgorithm = Optional.ofNullable(configuration)
                .map(SAML2Configuration::getSignatureAlgorithms)
                .filter(algorithms -> !algorithms.isEmpty())
                .map(algorithms -> algorithms.get(0))
                .orElse(this.signatureAlgorithm);
            signingParameters.setSignatureAlgorithm(signingAlgorithm);

            final var signingReference = Optional.ofNullable(configuration)
                .map(SAML2Configuration::getSignatureReferenceDigestMethods)
                .filter(algorithms -> !algorithms.isEmpty())
                .map(algorithms -> algorithms.get(0))
                .orElse(this.signatureReferenceDigestMethod);
            signingParameters.setSignatureReferenceDigestMethod(signingReference);

            signingParameters.setSignatureCanonicalizationAlgorithm(
                SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);

            SignatureSupport.signObject(descriptor, signingParameters);
        } catch (final Exception e) {
            throw new SAMLException(e.getMessage(), e);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy