Search in sources :

Example 36 with Assertion

use of org.opensaml.saml.saml2.core.Assertion in project cxf by apache.

the class SAMLUtils method getClaims.

/**
 * Extract Claims from a SAML Assertion
 */
public static ClaimCollection getClaims(SamlAssertionWrapper assertion) {
    ClaimCollection claims = new ClaimCollection();
    if (assertion.getSamlVersion().equals(SAMLVersion.VERSION_20)) {
        List<AttributeStatement> statements = assertion.getSaml2().getAttributeStatements();
        for (AttributeStatement as : statements) {
            for (Attribute atr : as.getAttributes()) {
                SAMLClaim claim = new SAMLClaim();
                claim.setClaimType(URI.create(atr.getName()));
                claim.setName(atr.getName());
                claim.setNameFormat(atr.getNameFormat());
                claim.setFriendlyName(atr.getFriendlyName());
                for (XMLObject o : atr.getAttributeValues()) {
                    String attrValue = o.getDOM().getTextContent();
                    claim.getValues().add(attrValue);
                }
                claims.add(claim);
            }
        }
    } else {
        List<org.opensaml.saml.saml1.core.AttributeStatement> attributeStatements = assertion.getSaml1().getAttributeStatements();
        for (org.opensaml.saml.saml1.core.AttributeStatement statement : attributeStatements) {
            for (org.opensaml.saml.saml1.core.Attribute atr : statement.getAttributes()) {
                SAMLClaim claim = new SAMLClaim();
                String claimType = atr.getAttributeName();
                if (atr.getAttributeNamespace() != null) {
                    claimType = atr.getAttributeNamespace() + "/" + claimType;
                }
                claim.setClaimType(URI.create(claimType));
                claim.setName(atr.getAttributeName());
                claim.setNameFormat(atr.getAttributeNamespace());
                for (XMLObject o : atr.getAttributeValues()) {
                    String attrValue = o.getDOM().getTextContent();
                    claim.getValues().add(attrValue);
                }
                claims.add(claim);
            }
        }
    }
    return claims;
}
Also used : SAMLClaim(org.apache.cxf.rt.security.saml.claims.SAMLClaim) Attribute(org.opensaml.saml.saml2.core.Attribute) XMLObject(org.opensaml.core.xml.XMLObject) AttributeStatement(org.opensaml.saml.saml2.core.AttributeStatement) ClaimCollection(org.apache.cxf.rt.security.claims.ClaimCollection)

Example 37 with Assertion

use of org.opensaml.saml.saml2.core.Assertion in project cxf by apache.

the class SAMLSSOResponseValidator method validateSamlResponse.

/**
 * Validate a SAML 2 Protocol Response
 * @param samlResponse
 * @param postBinding
 * @return a SSOValidatorResponse object
 * @throws WSSecurityException
 */
public SSOValidatorResponse validateSamlResponse(org.opensaml.saml.saml2.core.Response samlResponse, boolean postBinding) throws WSSecurityException {
    // Check the Issuer
    validateIssuer(samlResponse.getIssuer());
    // The Response must contain at least one Assertion.
    if (samlResponse.getAssertions() == null || samlResponse.getAssertions().isEmpty()) {
        LOG.fine("The Response must contain at least one Assertion");
        throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
    }
    // The Response must contain a Destination that matches the assertionConsumerURL if it is
    // signed
    String destination = samlResponse.getDestination();
    if (samlResponse.isSigned() && (destination == null || !destination.equals(assertionConsumerURL))) {
        LOG.fine("The Response must contain a destination that matches the assertion consumer URL");
        throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
    }
    if (enforceResponseSigned && !samlResponse.isSigned()) {
        LOG.fine("The Response must be signed!");
        throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
    }
    // Validate Assertions
    org.opensaml.saml.saml2.core.Assertion validAssertion = null;
    Instant sessionNotOnOrAfter = null;
    for (org.opensaml.saml.saml2.core.Assertion assertion : samlResponse.getAssertions()) {
        // Check the Issuer
        if (assertion.getIssuer() == null) {
            LOG.fine("Assertion Issuer must not be null");
            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
        }
        validateIssuer(assertion.getIssuer());
        if (!samlResponse.isSigned() && enforceAssertionsSigned && assertion.getSignature() == null) {
            LOG.fine("The enclosed assertions in the SAML Response must be signed");
            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
        }
        // Check for AuthnStatements and validate the Subject accordingly
        if (assertion.getAuthnStatements() != null && !assertion.getAuthnStatements().isEmpty()) {
            org.opensaml.saml.saml2.core.Subject subject = assertion.getSubject();
            org.opensaml.saml.saml2.core.SubjectConfirmation subjectConf = validateAuthenticationSubject(subject, assertion.getID(), postBinding);
            if (subjectConf != null) {
                validateAudienceRestrictionCondition(assertion.getConditions());
                validAssertion = assertion;
                // Store Session NotOnOrAfter
                for (AuthnStatement authnStatment : assertion.getAuthnStatements()) {
                    if (authnStatment.getSessionNotOnOrAfter() != null) {
                        sessionNotOnOrAfter = Instant.ofEpochMilli(authnStatment.getSessionNotOnOrAfter().toDate().getTime());
                    }
                }
                // Fall back to the SubjectConfirmationData NotOnOrAfter if we have no session NotOnOrAfter
                if (sessionNotOnOrAfter == null) {
                    sessionNotOnOrAfter = Instant.ofEpochMilli(subjectConf.getSubjectConfirmationData().getNotOnOrAfter().toDate().getTime());
                }
            }
        }
    }
    if (validAssertion == null) {
        LOG.fine("The Response did not contain any Authentication Statement that matched " + "the Subject Confirmation criteria");
        throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "invalidSAMLsecurity");
    }
    SSOValidatorResponse validatorResponse = new SSOValidatorResponse();
    validatorResponse.setResponseId(samlResponse.getID());
    validatorResponse.setSessionNotOnOrAfter(sessionNotOnOrAfter);
    if (samlResponse.getIssueInstant() != null) {
        validatorResponse.setCreated(Instant.ofEpochMilli(samlResponse.getIssueInstant().toDate().getTime()));
    }
    Element assertionElement = validAssertion.getDOM();
    Element clonedAssertionElement = (Element) assertionElement.cloneNode(true);
    validatorResponse.setAssertionElement(clonedAssertionElement);
    validatorResponse.setAssertion(DOM2Writer.nodeToString(clonedAssertionElement));
    validatorResponse.setOpensamlAssertion(validAssertion);
    return validatorResponse;
}
Also used : Instant(java.time.Instant) Element(org.w3c.dom.Element) AuthnStatement(org.opensaml.saml.saml2.core.AuthnStatement) WSSecurityException(org.apache.wss4j.common.ext.WSSecurityException)

Example 38 with Assertion

use of org.opensaml.saml.saml2.core.Assertion in project cxf by apache.

the class CombinedValidatorTest method createResponse.

private Response createResponse(Document doc) throws Exception {
    Status status = SAML2PResponseComponentBuilder.createStatus(SAMLProtocolResponseValidator.SAML2_STATUSCODE_SUCCESS, null);
    Response response = SAML2PResponseComponentBuilder.createSAMLResponse("http://cxf.apache.org/saml", "http://cxf.apache.org/issuer", status);
    response.setDestination("http://recipient.apache.org");
    // Create an AuthenticationAssertion
    SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
    callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
    callbackHandler.setIssuer("http://cxf.apache.org/issuer");
    callbackHandler.setConfirmationMethod(SAML2Constants.CONF_BEARER);
    callbackHandler.setSubjectName("alice");
    SubjectConfirmationDataBean subjectConfirmationData = new SubjectConfirmationDataBean();
    subjectConfirmationData.setAddress("http://apache.org");
    subjectConfirmationData.setInResponseTo("12345");
    subjectConfirmationData.setNotAfter(new DateTime().plusMinutes(5));
    subjectConfirmationData.setRecipient("http://recipient.apache.org");
    callbackHandler.setSubjectConfirmationData(subjectConfirmationData);
    ConditionsBean conditions = new ConditionsBean();
    conditions.setNotBefore(new DateTime());
    conditions.setNotAfter(new DateTime().plusMinutes(5));
    AudienceRestrictionBean audienceRestriction = new AudienceRestrictionBean();
    audienceRestriction.setAudienceURIs(Collections.singletonList("http://service.apache.org"));
    conditions.setAudienceRestrictions(Collections.singletonList(audienceRestriction));
    callbackHandler.setConditions(conditions);
    SAMLCallback samlCallback = new SAMLCallback();
    SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
    SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
    Crypto issuerCrypto = new Merlin();
    KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
    ClassLoader loader = Loader.getClassLoader(CombinedValidatorTest.class);
    InputStream input = Merlin.loadInputStream(loader, "alice.jks");
    keyStore.load(input, "password".toCharArray());
    ((Merlin) issuerCrypto).setKeyStore(keyStore);
    assertion.signAssertion("alice", "password", issuerCrypto, false);
    response.getAssertions().add(assertion.getSaml2());
    return response;
}
Also used : Status(org.opensaml.saml.saml2.core.Status) AudienceRestrictionBean(org.apache.wss4j.common.saml.bean.AudienceRestrictionBean) InputStream(java.io.InputStream) ConditionsBean(org.apache.wss4j.common.saml.bean.ConditionsBean) SamlAssertionWrapper(org.apache.wss4j.common.saml.SamlAssertionWrapper) KeyStore(java.security.KeyStore) DateTime(org.joda.time.DateTime) Response(org.opensaml.saml.saml2.core.Response) Crypto(org.apache.wss4j.common.crypto.Crypto) SubjectConfirmationDataBean(org.apache.wss4j.common.saml.bean.SubjectConfirmationDataBean) SAMLCallback(org.apache.wss4j.common.saml.SAMLCallback) Merlin(org.apache.wss4j.common.crypto.Merlin)

Example 39 with Assertion

use of org.opensaml.saml.saml2.core.Assertion in project cxf by apache.

the class CombinedValidatorTest method testWrappingAttack3.

@org.junit.Test
public void testWrappingAttack3() throws Exception {
    Document doc = DOMUtils.createDocument();
    Response response = createResponse(doc);
    Element responseElement = OpenSAMLUtil.toDom(response, doc);
    doc.appendChild(responseElement);
    assertNotNull(responseElement);
    // Get Assertion Element
    Element assertionElement = (Element) responseElement.getElementsByTagNameNS(SAMLConstants.SAML20_NS, "Assertion").item(0);
    assertNotNull(assertionElement);
    // Clone it, strip the Signature, modify the Subject, change Subj Conf
    Element clonedAssertion = (Element) assertionElement.cloneNode(true);
    clonedAssertion.setAttributeNS(null, "ID", "_12345623562");
    Element sigElement = (Element) clonedAssertion.getElementsByTagNameNS(WSS4JConstants.SIG_NS, "Signature").item(0);
    clonedAssertion.removeChild(sigElement);
    Element subjElement = (Element) clonedAssertion.getElementsByTagNameNS(SAMLConstants.SAML20_NS, "Subject").item(0);
    Element subjNameIdElement = (Element) subjElement.getElementsByTagNameNS(SAMLConstants.SAML20_NS, "NameID").item(0);
    subjNameIdElement.setTextContent("bob");
    Element subjConfElement = (Element) subjElement.getElementsByTagNameNS(SAMLConstants.SAML20_NS, "SubjectConfirmation").item(0);
    subjConfElement.setAttributeNS(null, "Method", SAML2Constants.CONF_SENDER_VOUCHES);
    // Now insert the modified cloned Assertion into the Response before actual assertion
    responseElement.insertBefore(clonedAssertion, assertionElement);
    // System.out.println(DOM2Writer.nodeToString(responseElement));
    Response marshalledResponse = (Response) OpenSAMLUtil.fromDom(responseElement);
    Crypto issuerCrypto = new Merlin();
    KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
    ClassLoader loader = Loader.getClassLoader(CombinedValidatorTest.class);
    InputStream input = Merlin.loadInputStream(loader, "alice.jks");
    keyStore.load(input, "password".toCharArray());
    ((Merlin) issuerCrypto).setKeyStore(keyStore);
    // Validate the Response
    SAMLProtocolResponseValidator validator = new SAMLProtocolResponseValidator();
    validator.validateSamlResponse(marshalledResponse, issuerCrypto, new KeystorePasswordCallback());
    // Test SSO validation
    SAMLSSOResponseValidator ssoValidator = new SAMLSSOResponseValidator();
    ssoValidator.setEnforceAssertionsSigned(false);
    ssoValidator.setIssuerIDP("http://cxf.apache.org/issuer");
    ssoValidator.setAssertionConsumerURL("http://recipient.apache.org");
    ssoValidator.setClientAddress("http://apache.org");
    ssoValidator.setRequestId("12345");
    ssoValidator.setSpIdentifier("http://service.apache.org");
    // Parse the response
    SSOValidatorResponse ssoResponse = ssoValidator.validateSamlResponse(marshalledResponse, false);
    SamlAssertionWrapper parsedAssertion = new SamlAssertionWrapper(ssoResponse.getAssertionElement());
    assertEquals("alice", parsedAssertion.getSubjectName());
}
Also used : InputStream(java.io.InputStream) Element(org.w3c.dom.Element) SamlAssertionWrapper(org.apache.wss4j.common.saml.SamlAssertionWrapper) Document(org.w3c.dom.Document) KeyStore(java.security.KeyStore) Response(org.opensaml.saml.saml2.core.Response) Crypto(org.apache.wss4j.common.crypto.Crypto) Merlin(org.apache.wss4j.common.crypto.Merlin)

Example 40 with Assertion

use of org.opensaml.saml.saml2.core.Assertion in project cxf by apache.

the class SAMLResponseValidatorTest method testStaleSessionNotOnOrAfter.

@org.junit.Test
public void testStaleSessionNotOnOrAfter() throws Exception {
    Document doc = DOMUtils.createDocument();
    Status status = SAML2PResponseComponentBuilder.createStatus(SAMLProtocolResponseValidator.SAML2_STATUSCODE_SUCCESS, null);
    Response response = SAML2PResponseComponentBuilder.createSAMLResponse("http://cxf.apache.org/saml", "http://cxf.apache.org/issuer", status);
    // Create an AuthenticationAssertion
    SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
    callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
    callbackHandler.setIssuer("http://cxf.apache.org/issuer");
    callbackHandler.setConfirmationMethod(SAML2Constants.CONF_SENDER_VOUCHES);
    callbackHandler.setSessionNotOnOrAfter(new DateTime().minusDays(1));
    SAMLCallback samlCallback = new SAMLCallback();
    SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
    SamlAssertionWrapper assertion = new SamlAssertionWrapper(samlCallback);
    response.getAssertions().add(assertion.getSaml2());
    Element policyElement = OpenSAMLUtil.toDom(response, doc);
    doc.appendChild(policyElement);
    assertNotNull(policyElement);
    Response marshalledResponse = (Response) OpenSAMLUtil.fromDom(policyElement);
    // Validate the Response
    SAMLProtocolResponseValidator validator = new SAMLProtocolResponseValidator();
    try {
        validator.validateSamlResponse(marshalledResponse, null, null);
        fail("Expected failure on an invalid SessionNotOnOrAfter");
    } catch (WSSecurityException ex) {
    // expected
    }
}
Also used : Status(org.opensaml.saml.saml2.core.Status) Response(org.opensaml.saml.saml2.core.Response) Element(org.w3c.dom.Element) SamlAssertionWrapper(org.apache.wss4j.common.saml.SamlAssertionWrapper) SAMLCallback(org.apache.wss4j.common.saml.SAMLCallback) WSSecurityException(org.apache.wss4j.common.ext.WSSecurityException) Document(org.w3c.dom.Document) DateTime(org.joda.time.DateTime)

Aggregations

Assertion (org.opensaml.saml.saml2.core.Assertion)33 Response (org.opensaml.saml.saml2.core.Response)31 Element (org.w3c.dom.Element)31 SamlAssertionWrapper (org.apache.wss4j.common.saml.SamlAssertionWrapper)26 Document (org.w3c.dom.Document)22 WSSecurityException (org.apache.wss4j.common.ext.WSSecurityException)20 Status (org.opensaml.saml.saml2.core.Status)20 SAMLCallback (org.apache.wss4j.common.saml.SAMLCallback)18 DateTime (org.joda.time.DateTime)16 Test (org.junit.Test)16 Assertion (org.opensaml.saml.saml1.core.Assertion)13 InputStream (java.io.InputStream)11 Crypto (org.apache.wss4j.common.crypto.Crypto)11 AttributeStatement (org.opensaml.saml.saml2.core.AttributeStatement)11 ZonedDateTime (java.time.ZonedDateTime)10 XMLObject (org.opensaml.core.xml.XMLObject)10 KeyStore (java.security.KeyStore)9 Merlin (org.apache.wss4j.common.crypto.Merlin)9 Assertion (org.jasig.cas.client.validation.Assertion)9 AuthnRequest (org.opensaml.saml.saml2.core.AuthnRequest)9