Search in sources :

Example 31 with AssertionType

use of org.keycloak.dom.saml.v2.assertion.AssertionType in project keycloak by keycloak.

the class AbstractSamlAuthenticationHandler method handleLoginResponse.

protected AuthOutcome handleLoginResponse(SAMLDocumentHolder responseHolder, boolean postBinding, OnSessionCreated onCreateSession) {
    if (!sessionStore.isLoggingIn()) {
        log.warn("Adapter obtained LoginResponse, however containers session is not aware of sending any request. " + "This may be because the session cookies created by container are not properly configured " + "with SameSite settings. Refer to KEYCLOAK-14103 for more details.");
    }
    final ResponseType responseType = (ResponseType) responseHolder.getSamlObject();
    AssertionType assertion = null;
    if (!isSuccessfulSamlResponse(responseType) || responseType.getAssertions() == null || responseType.getAssertions().isEmpty()) {
        return failed(createAuthChallenge403(responseType));
    }
    try {
        assertion = AssertionUtil.getAssertion(responseHolder, responseType, deployment.getDecryptionKey());
        ConditionsValidator.Builder cvb = new ConditionsValidator.Builder(assertion.getID(), assertion.getConditions(), destinationValidator);
        try {
            cvb.clockSkewInMillis(deployment.getIDP().getAllowedClockSkew());
            cvb.addAllowedAudience(URI.create(deployment.getEntityID()));
            if (responseType.getDestination() != null) {
                // getDestination has been validated to match request URL already so it matches SAML endpoint
                cvb.addAllowedAudience(URI.create(responseType.getDestination()));
            }
        } catch (IllegalArgumentException ex) {
        // warning has been already emitted in DeploymentBuilder
        }
        if (!cvb.build().isValid()) {
            return initiateLogin();
        }
    } catch (Exception e) {
        log.error("Error extracting SAML assertion: " + e.getMessage());
        return failed(CHALLENGE_EXTRACTION_FAILURE);
    }
    Element assertionElement = null;
    if (deployment.getIDP().getSingleSignOnService().validateAssertionSignature()) {
        try {
            assertionElement = getAssertionFromResponse(responseHolder);
            if (!AssertionUtil.isSignatureValid(assertionElement, deployment.getIDP().getSignatureValidationKeyLocator())) {
                log.error("Failed to verify saml assertion signature");
                return failed(CHALLENGE_INVALID_SIGNATURE);
            }
        } catch (Exception e) {
            log.error("Error processing validation of SAML assertion: " + e.getMessage());
            return failed(CHALLENGE_EXTRACTION_FAILURE);
        }
    }
    SubjectType subject = assertion.getSubject();
    SubjectType.STSubType subType = subject.getSubType();
    NameIDType subjectNameID = subType == null ? null : (NameIDType) subType.getBaseID();
    String principalName = subjectNameID == null ? null : subjectNameID.getValue();
    Set<String> roles = new HashSet<>();
    MultivaluedHashMap<String, String> attributes = new MultivaluedHashMap<>();
    MultivaluedHashMap<String, String> friendlyAttributes = new MultivaluedHashMap<>();
    Set<StatementAbstractType> statements = assertion.getStatements();
    for (StatementAbstractType statement : statements) {
        if (statement instanceof AttributeStatementType) {
            AttributeStatementType attributeStatement = (AttributeStatementType) statement;
            List<AttributeStatementType.ASTChoiceType> attList = attributeStatement.getAttributes();
            for (AttributeStatementType.ASTChoiceType obj : attList) {
                AttributeType attr = obj.getAttribute();
                if (isRole(attr)) {
                    List<Object> attributeValues = attr.getAttributeValue();
                    if (attributeValues != null) {
                        for (Object attrValue : attributeValues) {
                            String role = getAttributeValue(attrValue);
                            log.debugv("Add role: {0}", role);
                            roles.add(role);
                        }
                    }
                } else {
                    List<Object> attributeValues = attr.getAttributeValue();
                    if (attributeValues != null) {
                        for (Object attrValue : attributeValues) {
                            String value = getAttributeValue(attrValue);
                            if (attr.getName() != null) {
                                attributes.add(attr.getName(), value);
                            }
                            if (attr.getFriendlyName() != null) {
                                friendlyAttributes.add(attr.getFriendlyName(), value);
                            }
                        }
                    }
                }
            }
        }
    }
    if (deployment.getPrincipalNamePolicy() == SamlDeployment.PrincipalNamePolicy.FROM_ATTRIBUTE) {
        if (deployment.getPrincipalAttributeName() != null) {
            String attribute = attributes.getFirst(deployment.getPrincipalAttributeName());
            if (attribute != null)
                principalName = attribute;
            else {
                attribute = friendlyAttributes.getFirst(deployment.getPrincipalAttributeName());
                if (attribute != null)
                    principalName = attribute;
            }
        }
    }
    // use the configured role mappings provider to map roles if necessary.
    if (deployment.getRoleMappingsProvider() != null) {
        roles = deployment.getRoleMappingsProvider().map(principalName, roles);
    }
    // roles should also be there as regular attributes
    // this mainly required for elytron and its ABAC nature
    attributes.put(DEFAULT_ROLE_ATTRIBUTE_NAME, new ArrayList<>(roles));
    AuthnStatementType authn = null;
    for (Object statement : assertion.getStatements()) {
        if (statement instanceof AuthnStatementType) {
            authn = (AuthnStatementType) statement;
            break;
        }
    }
    URI nameFormat = subjectNameID == null ? null : subjectNameID.getFormat();
    String nameFormatString = nameFormat == null ? JBossSAMLURIConstants.NAMEID_FORMAT_UNSPECIFIED.get() : nameFormat.toString();
    if (deployment.isKeepDOMAssertion() && assertionElement == null) {
        // obtain the assertion from the response to add the DOM document to the principal
        assertionElement = getAssertionFromResponseNoException(responseHolder);
    }
    final SamlPrincipal principal = new SamlPrincipal(assertion, deployment.isKeepDOMAssertion() ? getAssertionDocumentFromElement(assertionElement) : null, principalName, principalName, nameFormatString, attributes, friendlyAttributes);
    final String sessionIndex = authn == null ? null : authn.getSessionIndex();
    final XMLGregorianCalendar sessionNotOnOrAfter = authn == null ? null : authn.getSessionNotOnOrAfter();
    SamlSession account = new SamlSession(principal, roles, sessionIndex, sessionNotOnOrAfter);
    sessionStore.saveAccount(account);
    onCreateSession.onSessionCreated(account);
    // redirect to original request, it will be restored
    String redirectUri = sessionStore.getRedirectUri();
    if (redirectUri != null) {
        facade.getResponse().setHeader("Location", redirectUri);
        facade.getResponse().setStatus(302);
        facade.getResponse().end();
    } else {
        log.debug("IDP initiated invocation");
    }
    log.debug("AUTHENTICATED authn");
    return AuthOutcome.AUTHENTICATED;
}
Also used : SAML2AuthnRequestBuilder(org.keycloak.saml.SAML2AuthnRequestBuilder) KeycloakUriBuilder(org.keycloak.common.util.KeycloakUriBuilder) BaseSAML2BindingBuilder(org.keycloak.saml.BaseSAML2BindingBuilder) Element(org.w3c.dom.Element) URI(java.net.URI) MultivaluedHashMap(org.keycloak.common.util.MultivaluedHashMap) AuthnStatementType(org.keycloak.dom.saml.v2.assertion.AuthnStatementType) SubjectType(org.keycloak.dom.saml.v2.assertion.SubjectType) AttributeType(org.keycloak.dom.saml.v2.assertion.AttributeType) NameIDType(org.keycloak.dom.saml.v2.assertion.NameIDType) AttributeStatementType(org.keycloak.dom.saml.v2.assertion.AttributeStatementType) AssertionType(org.keycloak.dom.saml.v2.assertion.AssertionType) SamlSession(org.keycloak.adapters.saml.SamlSession) 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) ResponseType(org.keycloak.dom.saml.v2.protocol.ResponseType) StatusResponseType(org.keycloak.dom.saml.v2.protocol.StatusResponseType) XMLGregorianCalendar(javax.xml.datatype.XMLGregorianCalendar) SamlPrincipal(org.keycloak.adapters.saml.SamlPrincipal) SAML2Object(org.keycloak.dom.saml.v2.SAML2Object) ConditionsValidator(org.keycloak.saml.validators.ConditionsValidator) StatementAbstractType(org.keycloak.dom.saml.v2.assertion.StatementAbstractType)

Example 32 with AssertionType

use of org.keycloak.dom.saml.v2.assertion.AssertionType in project keycloak by keycloak.

the class SAMLDataMarshaller method serialize.

@Override
public String serialize(Object obj) {
    // Lame impl, but hopefully sufficient for now. See if something better is needed...
    if (obj.getClass().getName().startsWith("org.keycloak.dom.saml")) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            if (obj instanceof ResponseType) {
                ResponseType responseType = (ResponseType) obj;
                SAMLResponseWriter samlWriter = new SAMLResponseWriter(StaxUtil.getXMLStreamWriter(bos));
                samlWriter.write(responseType);
            } else if (obj instanceof AssertionType) {
                AssertionType assertion = (AssertionType) obj;
                SAMLAssertionWriter samlWriter = new SAMLAssertionWriter(StaxUtil.getXMLStreamWriter(bos));
                samlWriter.write(assertion);
            } else if (obj instanceof AuthnStatementType) {
                AuthnStatementType authnStatement = (AuthnStatementType) obj;
                SAMLAssertionWriter samlWriter = new SAMLAssertionWriter(StaxUtil.getXMLStreamWriter(bos));
                samlWriter.write(authnStatement, true);
            } else if (obj instanceof ArtifactResponseType) {
                ArtifactResponseType artifactResponseType = (ArtifactResponseType) obj;
                SAMLResponseWriter samlWriter = new SAMLResponseWriter(StaxUtil.getXMLStreamWriter(bos));
                samlWriter.write(artifactResponseType);
            } else {
                throw new IllegalArgumentException("Don't know how to serialize object of type " + obj.getClass().getName());
            }
        } catch (ProcessingException pe) {
            throw new RuntimeException(pe);
        }
        return new String(bos.toByteArray(), GeneralConstants.SAML_CHARSET);
    } else {
        return super.serialize(obj);
    }
}
Also used : AuthnStatementType(org.keycloak.dom.saml.v2.assertion.AuthnStatementType) SAMLResponseWriter(org.keycloak.saml.processing.core.saml.v2.writers.SAMLResponseWriter) ArtifactResponseType(org.keycloak.dom.saml.v2.protocol.ArtifactResponseType) ByteArrayOutputStream(java.io.ByteArrayOutputStream) AssertionType(org.keycloak.dom.saml.v2.assertion.AssertionType) SAMLAssertionWriter(org.keycloak.saml.processing.core.saml.v2.writers.SAMLAssertionWriter) ArtifactResponseType(org.keycloak.dom.saml.v2.protocol.ArtifactResponseType) ResponseType(org.keycloak.dom.saml.v2.protocol.ResponseType) ProcessingException(org.keycloak.saml.common.exceptions.ProcessingException)

Example 33 with AssertionType

use of org.keycloak.dom.saml.v2.assertion.AssertionType in project keycloak by keycloak.

the class SAMLIdentityProvider method authenticationFinished.

@Override
public void authenticationFinished(AuthenticationSessionModel authSession, BrokeredIdentityContext context) {
    ResponseType responseType = (ResponseType) context.getContextData().get(SAMLEndpoint.SAML_LOGIN_RESPONSE);
    AssertionType assertion = (AssertionType) context.getContextData().get(SAMLEndpoint.SAML_ASSERTION);
    SubjectType subject = assertion.getSubject();
    SubjectType.STSubType subType = subject.getSubType();
    if (subType != null) {
        NameIDType subjectNameID = (NameIDType) subType.getBaseID();
        authSession.setUserSessionNote(SAMLEndpoint.SAML_FEDERATED_SUBJECT_NAMEID, subjectNameID.serializeAsString());
    }
    AuthnStatementType authn = (AuthnStatementType) context.getContextData().get(SAMLEndpoint.SAML_AUTHN_STATEMENT);
    if (authn != null && authn.getSessionIndex() != null) {
        authSession.setUserSessionNote(SAMLEndpoint.SAML_FEDERATED_SESSION_INDEX, authn.getSessionIndex());
    }
}
Also used : AuthnStatementType(org.keycloak.dom.saml.v2.assertion.AuthnStatementType) SubjectType(org.keycloak.dom.saml.v2.assertion.SubjectType) AssertionType(org.keycloak.dom.saml.v2.assertion.AssertionType) NameIDType(org.keycloak.dom.saml.v2.assertion.NameIDType) ResponseType(org.keycloak.dom.saml.v2.protocol.ResponseType)

Example 34 with AssertionType

use of org.keycloak.dom.saml.v2.assertion.AssertionType in project keycloak by keycloak.

the class SAML2Response method createResponseType.

/**
 * Create a ResponseType
 *
 * <b>NOTE:</b>: The PicketLink STS is used to issue/update the assertion
 *
 * If you want to control over the assertion being issued, then use
 * {@link #createResponseType(String, SPInfoHolder, IDPInfoHolder, IssuerInfoHolder, AssertionType)}
 *
 * @param ID id of the response
 * @param sp holder with the information about the Service Provider
 * @param idp holder with the information on the Identity Provider
 * @param issuerInfo holder with information on the issuer
 *
 * @return
 *
 * @throws ConfigurationException
 * @throws ProcessingException
 */
public ResponseType createResponseType(String ID, SPInfoHolder sp, IDPInfoHolder idp, IssuerInfoHolder issuerInfo) throws ProcessingException {
    String responseDestinationURI = sp.getResponseDestinationURI();
    XMLGregorianCalendar issueInstant = XMLTimeUtil.getIssueInstant();
    // Create assertion -> subject
    SubjectType subjectType = new SubjectType();
    // subject -> nameid
    NameIDType nameIDType = new NameIDType();
    nameIDType.setFormat(idp.getNameIDFormat() == null ? null : URI.create(idp.getNameIDFormat()));
    nameIDType.setValue(idp.getNameIDFormatValue());
    SubjectType.STSubType subType = new SubjectType.STSubType();
    subType.addBaseID(nameIDType);
    subjectType.setSubType(subType);
    SubjectConfirmationType subjectConfirmation = new SubjectConfirmationType();
    subjectConfirmation.setMethod(idp.getSubjectConfirmationMethod());
    SubjectConfirmationDataType subjectConfirmationData = new SubjectConfirmationDataType();
    subjectConfirmationData.setInResponseTo(sp.getRequestID());
    subjectConfirmationData.setRecipient(responseDestinationURI);
    // subjectConfirmationData.setNotBefore(issueInstant);
    subjectConfirmationData.setNotOnOrAfter(issueInstant);
    subjectConfirmation.setSubjectConfirmationData(subjectConfirmationData);
    subjectType.addConfirmation(subjectConfirmation);
    AssertionType assertionType;
    NameIDType issuerID = issuerInfo.getIssuer();
    issueInstant = XMLTimeUtil.getIssueInstant();
    ConditionsType conditions = null;
    List<StatementAbstractType> statements = new LinkedList<>();
    // generate an id for the new assertion.
    String assertionID = IDGenerator.create("ID_");
    assertionType = SAMLAssertionFactory.createAssertion(assertionID, issuerID, issueInstant, conditions, subjectType, statements);
    try {
        AssertionUtil.createTimedConditions(assertionType, ASSERTION_VALIDITY, CLOCK_SKEW);
    } catch (ConfigurationException e) {
        throw logger.processingError(e);
    } catch (IssueInstantMissingException e) {
        throw logger.processingError(e);
    }
    ResponseType responseType = createResponseType(ID, issuerInfo, assertionType);
    // InResponseTo ID
    responseType.setInResponseTo(sp.getRequestID());
    // Destination
    responseType.setDestination(responseDestinationURI);
    return responseType;
}
Also used : EncryptedAssertionType(org.keycloak.dom.saml.v2.assertion.EncryptedAssertionType) AssertionType(org.keycloak.dom.saml.v2.assertion.AssertionType) LinkedList(java.util.LinkedList) IssueInstantMissingException(org.keycloak.saml.common.exceptions.fed.IssueInstantMissingException) ResponseType(org.keycloak.dom.saml.v2.protocol.ResponseType) StatusResponseType(org.keycloak.dom.saml.v2.protocol.StatusResponseType) XMLGregorianCalendar(javax.xml.datatype.XMLGregorianCalendar) SubjectType(org.keycloak.dom.saml.v2.assertion.SubjectType) SubjectConfirmationDataType(org.keycloak.dom.saml.v2.assertion.SubjectConfirmationDataType) SubjectConfirmationType(org.keycloak.dom.saml.v2.assertion.SubjectConfirmationType) ConfigurationException(org.keycloak.saml.common.exceptions.ConfigurationException) ConditionsType(org.keycloak.dom.saml.v2.assertion.ConditionsType) NameIDType(org.keycloak.dom.saml.v2.assertion.NameIDType) StatementAbstractType(org.keycloak.dom.saml.v2.assertion.StatementAbstractType)

Example 35 with AssertionType

use of org.keycloak.dom.saml.v2.assertion.AssertionType in project keycloak by keycloak.

the class SAML2LoginResponseBuilder method buildModel.

public ResponseType buildModel() throws ConfigurationException, ProcessingException {
    ResponseType responseType = null;
    SAML2Response saml2Response = new SAML2Response();
    // Create a response type
    String id = IDGenerator.create("ID_");
    IssuerInfoHolder issuerHolder = new IssuerInfoHolder(issuer);
    issuerHolder.setStatusCode(JBossSAMLURIConstants.STATUS_SUCCESS.get());
    IDPInfoHolder idp = new IDPInfoHolder();
    idp.setNameIDFormatValue(nameId);
    idp.setNameIDFormat(nameIdFormat);
    SPInfoHolder sp = new SPInfoHolder();
    sp.setResponseDestinationURI(destination);
    sp.setRequestID(requestID);
    sp.setIssuer(requestIssuer);
    responseType = saml2Response.createResponseType(id, sp, idp, issuerHolder);
    AssertionType assertion = responseType.getAssertions().get(0).getAssertion();
    // Add request issuer as the audience restriction
    AudienceRestrictionType audience = new AudienceRestrictionType();
    audience.addAudience(URI.create(requestIssuer));
    assertion.getConditions().addCondition(audience);
    // Update Conditions NotOnOrAfter
    if (assertionExpiration > 0) {
        ConditionsType conditions = assertion.getConditions();
        conditions.setNotOnOrAfter(XMLTimeUtil.add(conditions.getNotBefore(), assertionExpiration * 1000L));
    }
    // Update SubjectConfirmationData NotOnOrAfter
    if (subjectExpiration > 0) {
        SubjectConfirmationDataType subjectConfirmationData = assertion.getSubject().getConfirmation().get(0).getSubjectConfirmationData();
        subjectConfirmationData.setNotOnOrAfter(XMLTimeUtil.add(assertion.getConditions().getNotBefore(), subjectExpiration * 1000L));
    }
    // Create an AuthnStatementType
    if (!disableAuthnStatement) {
        String authContextRef = JBossSAMLURIConstants.AC_UNSPECIFIED.get();
        if (isNotNull(authMethod))
            authContextRef = authMethod;
        AuthnStatementType authnStatement = StatementUtil.createAuthnStatement(XMLTimeUtil.getIssueInstant(), authContextRef);
        if (sessionExpiration > 0)
            authnStatement.setSessionNotOnOrAfter(XMLTimeUtil.add(authnStatement.getAuthnInstant(), sessionExpiration * 1000L));
        if (sessionIndex != null)
            authnStatement.setSessionIndex(sessionIndex);
        else
            authnStatement.setSessionIndex(assertion.getID());
        assertion.addStatement(authnStatement);
    }
    if (includeOneTimeUseCondition) {
        assertion.getConditions().addCondition(new OneTimeUseType());
    }
    if (!this.extensions.isEmpty()) {
        ExtensionsType extensionsType = new ExtensionsType();
        for (NodeGenerator extension : this.extensions) {
            extensionsType.addExtension(extension);
        }
        responseType.setExtensions(extensionsType);
    }
    return responseType;
}
Also used : AudienceRestrictionType(org.keycloak.dom.saml.v2.assertion.AudienceRestrictionType) AssertionType(org.keycloak.dom.saml.v2.assertion.AssertionType) ResponseType(org.keycloak.dom.saml.v2.protocol.ResponseType) AuthnStatementType(org.keycloak.dom.saml.v2.assertion.AuthnStatementType) OneTimeUseType(org.keycloak.dom.saml.v2.assertion.OneTimeUseType) SubjectConfirmationDataType(org.keycloak.dom.saml.v2.assertion.SubjectConfirmationDataType) SPInfoHolder(org.keycloak.saml.processing.core.saml.v2.holders.SPInfoHolder) ExtensionsType(org.keycloak.dom.saml.v2.protocol.ExtensionsType) IssuerInfoHolder(org.keycloak.saml.processing.core.saml.v2.holders.IssuerInfoHolder) SAML2Response(org.keycloak.saml.processing.api.saml.v2.response.SAML2Response) ConditionsType(org.keycloak.dom.saml.v2.assertion.ConditionsType) IDPInfoHolder(org.keycloak.saml.processing.core.saml.v2.holders.IDPInfoHolder)

Aggregations

AssertionType (org.keycloak.dom.saml.v2.assertion.AssertionType)43 Test (org.junit.Test)24 ResponseType (org.keycloak.dom.saml.v2.protocol.ResponseType)21 NameIDType (org.keycloak.dom.saml.v2.assertion.NameIDType)20 EncryptedAssertionType (org.keycloak.dom.saml.v2.assertion.EncryptedAssertionType)15 AttributeStatementType (org.keycloak.dom.saml.v2.assertion.AttributeStatementType)13 AttributeType (org.keycloak.dom.saml.v2.assertion.AttributeType)13 Element (org.w3c.dom.Element)12 List (java.util.List)11 XMLGregorianCalendar (javax.xml.datatype.XMLGregorianCalendar)11 AuthnStatementType (org.keycloak.dom.saml.v2.assertion.AuthnStatementType)10 Document (org.w3c.dom.Document)10 AudienceRestrictionType (org.keycloak.dom.saml.v2.assertion.AudienceRestrictionType)9 ConditionsType (org.keycloak.dom.saml.v2.assertion.ConditionsType)9 SubjectType (org.keycloak.dom.saml.v2.assertion.SubjectType)9 StatementAbstractType (org.keycloak.dom.saml.v2.assertion.StatementAbstractType)8 ProcessingException (org.keycloak.saml.common.exceptions.ProcessingException)8 HashMap (java.util.HashMap)7 StatusResponseType (org.keycloak.dom.saml.v2.protocol.StatusResponseType)7 SAML2Object (org.keycloak.dom.saml.v2.SAML2Object)6