Search in sources :

Example 6 with EncryptedID

use of org.opensaml.saml.saml2.core.EncryptedID in project cas by apereo.

the class SamlIdPObjectEncrypter method decode.

/**
 * Decode name id.
 *
 * @param encryptedId the encrypted id
 * @param service     the service
 * @param adaptor     the adaptor
 * @return the name id
 */
public NameID decode(final EncryptedID encryptedId, final SamlRegisteredService service, final SamlRegisteredServiceServiceProviderMetadataFacade adaptor) {
    try {
        Security.addProvider(new BouncyCastleProvider());
        val config = configureDecryptionSecurityConfiguration(service);
        configureKeyDecryptionCredential(adaptor.getEntityId(), adaptor, service, config);
        val parameters = resolveDecryptionParameters(service, config);
        val decrypter = getDecrypter(encryptedId, service, adaptor, parameters);
        return (NameID) decrypter.decrypt(encryptedId);
    } catch (final Exception e) {
        throw new DecryptionException(e);
    }
}
Also used : lombok.val(lombok.val) NameID(org.opensaml.saml.saml2.core.NameID) DecryptionException(org.apereo.cas.util.crypto.DecryptionException) SamlException(org.apereo.cas.support.saml.SamlException) ResolverException(net.shibboleth.utilities.java.support.resolver.ResolverException) DecryptionException(org.apereo.cas.util.crypto.DecryptionException) BouncyCastleProvider(org.bouncycastle.jce.provider.BouncyCastleProvider)

Example 7 with EncryptedID

use of org.opensaml.saml.saml2.core.EncryptedID in project pac4j by pac4j.

the class AbstractSAML2ResponseValidator method decryptEncryptedId.

/**
 * Decrypts an EncryptedID, using a decrypter.
 *
 * @param encryptedId The EncryptedID to be decrypted.
 * @param decrypter   The decrypter to use.
 * @return Decrypted ID or {@code null} if any input is {@code null}.
 * @throws SAMLException If the input ID cannot be decrypted.
 */
protected NameID decryptEncryptedId(final EncryptedID encryptedId, final Decrypter decrypter) throws SAMLException {
    if (encryptedId == null) {
        return null;
    }
    if (decrypter == null) {
        logger.warn("Encrypted attributes returned, but no keystore was provided.");
        return null;
    }
    try {
        logger.debug("Decrypting name id {}", encryptedId);
        final var decryptedId = (NameID) decrypter.decrypt(encryptedId);
        return decryptedId;
    } catch (final DecryptionException e) {
        throw new SAMLNameIdDecryptionException("Decryption of an EncryptedID failed.", e);
    }
}
Also used : NameID(org.opensaml.saml.saml2.core.NameID) DecryptionException(org.opensaml.xmlsec.encryption.support.DecryptionException) SAMLNameIdDecryptionException(org.pac4j.saml.exceptions.SAMLNameIdDecryptionException) SAMLNameIdDecryptionException(org.pac4j.saml.exceptions.SAMLNameIdDecryptionException)

Example 8 with EncryptedID

use of org.opensaml.saml.saml2.core.EncryptedID in project pac4j by pac4j.

the class SAML2DefaultResponseValidator method validateSubject.

/**
 * Validate the given subject by finding a valid Bearer confirmation. If the subject is valid, put its nameID in the context.
 * <p>
 * NameID / BaseID / EncryptedID is first looked up directly in the Subject. If not present there, then all relevant
 * SubjectConfirmations are parsed and the IDs are taken from them.
 *
 * @param subject   The Subject from an assertion.
 * @param context   SAML message context.
 * @param decrypter Decrypter used to decrypt some encrypted IDs, if they are present.
 *                  May be {@code null}, no decryption will be possible then.
 */
@SuppressWarnings("unchecked")
protected final void validateSubject(final Subject subject, final SAML2MessageContext context, final Decrypter decrypter) {
    boolean samlIDFound = false;
    // Read NameID/BaseID/EncryptedID from the subject. If not present directly in the subject, try to find it in subject confirmations.
    NameID nameIdFromSubject = subject.getNameID();
    final BaseID baseIdFromSubject = subject.getBaseID();
    final EncryptedID encryptedIdFromSubject = subject.getEncryptedID();
    // Encrypted ID can overwrite the non-encrypted one, if present
    final NameID decryptedNameIdFromSubject = decryptEncryptedId(encryptedIdFromSubject, decrypter);
    if (decryptedNameIdFromSubject != null) {
        nameIdFromSubject = decryptedNameIdFromSubject;
    }
    // At least one should be present but we don't care at this point.
    if (nameIdFromSubject != null || baseIdFromSubject != null) {
        context.getSAMLSubjectNameIdentifierContext().setSubjectNameIdentifier(nameIdFromSubject);
        context.setBaseID(baseIdFromSubject);
        samlIDFound = true;
    }
    for (final SubjectConfirmation confirmation : subject.getSubjectConfirmations()) {
        if (SubjectConfirmation.METHOD_BEARER.equals(confirmation.getMethod()) && isValidBearerSubjectConfirmationData(confirmation.getSubjectConfirmationData(), context)) {
            NameID nameIDFromConfirmation = confirmation.getNameID();
            final BaseID baseIDFromConfirmation = confirmation.getBaseID();
            final EncryptedID encryptedIDFromConfirmation = confirmation.getEncryptedID();
            // Encrypted ID can overwrite the non-encrypted one, if present
            final NameID decryptedNameIdFromConfirmation = decryptEncryptedId(encryptedIDFromConfirmation, decrypter);
            if (decryptedNameIdFromConfirmation != null) {
                nameIDFromConfirmation = decryptedNameIdFromConfirmation;
            }
            if (!samlIDFound && (nameIDFromConfirmation != null || baseIDFromConfirmation != null)) {
                context.getSAMLSubjectNameIdentifierContext().setSubjectNameIdentifier(nameIDFromConfirmation);
                context.setBaseID(baseIDFromConfirmation);
                context.getSubjectConfirmations().add(confirmation);
                samlIDFound = true;
            }
            if (!samlIDFound) {
                logger.warn("Could not find any Subject NameID/BaseID/EncryptedID, neither directly in the Subject nor in any Subject " + "Confirmation.");
            }
            return;
        }
    }
    throw new SAMLSubjectConfirmationException("Subject confirmation validation failed");
}
Also used : BaseID(org.opensaml.saml.saml2.core.BaseID) SubjectConfirmation(org.opensaml.saml.saml2.core.SubjectConfirmation) NameID(org.opensaml.saml.saml2.core.NameID) EncryptedID(org.opensaml.saml.saml2.core.EncryptedID) SAMLSubjectConfirmationException(org.pac4j.saml.exceptions.SAMLSubjectConfirmationException)

Example 9 with EncryptedID

use of org.opensaml.saml.saml2.core.EncryptedID in project pac4j by pac4j.

the class SAML2DefaultResponseValidator method validateSamlSSOResponse.

/**
 * Validates the SAML SSO response by finding a valid assertion with authn statements.
 * Populates the {@link SAML2MessageContext} with a subjectAssertion and a subjectNameIdentifier.
 *
 * @param response  the response
 * @param context   the context
 * @param engine    the engine
 * @param decrypter the decrypter
 */
protected final void validateSamlSSOResponse(final Response response, final SAML2MessageContext context, final SignatureTrustEngine engine, final Decrypter decrypter) {
    final List<SAMLException> errors = new ArrayList<>();
    for (final Assertion assertion : response.getAssertions()) {
        if (!assertion.getAuthnStatements().isEmpty()) {
            try {
                validateAssertion(assertion, context, engine, decrypter);
            } catch (final SAMLException e) {
                logger.error("Current assertion validation failed, continue with the next one", e);
                errors.add(e);
                continue;
            }
            context.setSubjectAssertion(assertion);
            break;
        }
    }
    if (!errors.isEmpty()) {
        throw errors.get(0);
    }
    if (context.getSubjectAssertion() == null) {
        throw new SAMAssertionSubjectException("No valid subject assertion found in response");
    }
    // We do not check EncryptedID here because it has been already decrypted and stored into NameID
    final List<SubjectConfirmation> subjectConfirmations = context.getSubjectConfirmations();
    final NameID nameIdentifier = (NameID) context.getSAMLSubjectNameIdentifierContext().getSubjectNameIdentifier();
    if ((nameIdentifier == null || nameIdentifier.getValue() == null) && context.getBaseID() == null && (subjectConfirmations == null || subjectConfirmations.isEmpty())) {
        throw new SAMLException("Subject NameID, BaseID and EncryptedID cannot be all null at the same time if there are no Subject Confirmations.");
    }
}
Also used : SAMAssertionSubjectException(org.pac4j.saml.exceptions.SAMAssertionSubjectException) SubjectConfirmation(org.opensaml.saml.saml2.core.SubjectConfirmation) NameID(org.opensaml.saml.saml2.core.NameID) ArrayList(java.util.ArrayList) EncryptedAssertion(org.opensaml.saml.saml2.core.EncryptedAssertion) Assertion(org.opensaml.saml.saml2.core.Assertion) SAMLException(org.pac4j.saml.exceptions.SAMLException)

Example 10 with EncryptedID

use of org.opensaml.saml.saml2.core.EncryptedID in project cas by apereo.

the class AbstractSaml20ObjectBuilder method newSubject.

/**
 * New subject element.
 *
 * @param nameId            the nameId
 * @param subjectConfNameId the subject conf name id
 * @param recipient         the recipient
 * @param notOnOrAfter      the not on or after
 * @param inResponseTo      the in response to
 * @param notBefore         the not before
 * @return the subject
 */
public Subject newSubject(final SAMLObject nameId, final SAMLObject subjectConfNameId, final String recipient, final ZonedDateTime notOnOrAfter, final String inResponseTo, final ZonedDateTime notBefore) {
    LOGGER.debug("Building subject for NameID [{}] and recipient [{}], in response to [{}]", nameId, recipient, inResponseTo);
    val confirmation = newSamlObject(SubjectConfirmation.class);
    confirmation.setMethod(SubjectConfirmation.METHOD_BEARER);
    val data = newSamlObject(SubjectConfirmationData.class);
    if (StringUtils.isNotBlank(recipient)) {
        data.setRecipient(recipient);
    }
    if (notOnOrAfter != null) {
        data.setNotOnOrAfter(notOnOrAfter.toInstant());
    }
    if (StringUtils.isNotBlank(inResponseTo)) {
        data.setInResponseTo(inResponseTo);
        val ip = InetAddressUtils.getByName(inResponseTo);
        if (ip != null) {
            data.setAddress(ip.getHostName());
        }
    }
    if (notBefore != null) {
        data.setNotBefore(notBefore.toInstant());
    }
    confirmation.setSubjectConfirmationData(data);
    val subject = newSamlObject(Subject.class);
    subject.setNameID(null);
    subject.getSubjectConfirmations().forEach(c -> c.setNameID(null));
    if (nameId instanceof NameID) {
        subject.setNameID((NameID) nameId);
        subject.setEncryptedID(null);
    }
    if (nameId instanceof EncryptedID) {
        subject.setNameID(null);
        subject.setEncryptedID((EncryptedID) nameId);
    }
    if (subjectConfNameId instanceof NameID) {
        confirmation.setNameID((NameID) subjectConfNameId);
        confirmation.setEncryptedID(null);
    }
    if (subjectConfNameId instanceof EncryptedID) {
        confirmation.setNameID(null);
        confirmation.setEncryptedID((EncryptedID) subjectConfNameId);
    }
    subject.getSubjectConfirmations().add(confirmation);
    LOGGER.debug("Built subject [{}]", subject);
    return subject;
}
Also used : lombok.val(lombok.val) NameID(org.opensaml.saml.saml2.core.NameID) EncryptedID(org.opensaml.saml.saml2.core.EncryptedID)

Aggregations

NameID (org.opensaml.saml.saml2.core.NameID)11 EncryptedID (org.opensaml.saml.saml2.core.EncryptedID)8 Assertion (org.opensaml.saml.saml2.core.Assertion)5 EncryptedAssertion (org.opensaml.saml.saml2.core.EncryptedAssertion)5 Test (org.junit.jupiter.api.Test)4 Response (org.opensaml.saml.saml2.core.Response)4 NameIDBuilder (org.opensaml.saml.saml2.core.impl.NameIDBuilder)3 lombok.val (lombok.val)2 SubjectConfirmation (org.opensaml.saml.saml2.core.SubjectConfirmation)2 EncryptedIDBuilder (org.opensaml.saml.saml2.core.impl.EncryptedIDBuilder)2 EncryptedDataBuilder (org.opensaml.xmlsec.encryption.impl.EncryptedDataBuilder)2 Authentication (org.springframework.security.core.Authentication)2 X509Certificate (java.security.cert.X509Certificate)1 ArrayList (java.util.ArrayList)1 ResolverException (net.shibboleth.utilities.java.support.resolver.ResolverException)1 SamlException (org.apereo.cas.support.saml.SamlException)1 DecryptionException (org.apereo.cas.util.crypto.DecryptionException)1 BouncyCastleProvider (org.bouncycastle.jce.provider.BouncyCastleProvider)1 BaseID (org.opensaml.saml.saml2.core.BaseID)1 Issuer (org.opensaml.saml.saml2.core.Issuer)1