blob: d3e19fc5879cad82c89a3ce6c20267f304dd003c [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.wss4j.common.saml.builder;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.common.saml.OpenSAMLUtil;
import org.apache.wss4j.common.saml.bean.ActionBean;
import org.apache.wss4j.common.saml.bean.AdviceBean;
import org.apache.wss4j.common.saml.bean.AttributeBean;
import org.apache.wss4j.common.saml.bean.AttributeStatementBean;
import org.apache.wss4j.common.saml.bean.AudienceRestrictionBean;
import org.apache.wss4j.common.saml.bean.AuthDecisionStatementBean;
import org.apache.wss4j.common.saml.bean.AuthenticationStatementBean;
import org.apache.wss4j.common.saml.bean.ConditionsBean;
import org.apache.wss4j.common.saml.bean.DelegateBean;
import org.apache.wss4j.common.saml.bean.KeyInfoBean;
import org.apache.wss4j.common.saml.bean.NameIDBean;
import org.apache.wss4j.common.saml.bean.ProxyRestrictionBean;
import org.apache.wss4j.common.saml.bean.SubjectBean;
import org.apache.wss4j.common.saml.bean.SubjectConfirmationDataBean;
import org.apache.wss4j.common.saml.bean.SubjectLocalityBean;
import org.apache.xml.security.stax.impl.util.IDGenerator;
import org.opensaml.core.xml.XMLObject;
import org.opensaml.core.xml.XMLObjectBuilderFactory;
import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport;
import org.opensaml.core.xml.schema.XSString;
import org.opensaml.core.xml.schema.impl.XSStringBuilder;
import org.opensaml.saml.common.SAMLObjectBuilder;
import org.opensaml.saml.common.SAMLVersion;
import org.opensaml.saml.ext.saml2delrestrict.Delegate;
import org.opensaml.saml.ext.saml2delrestrict.DelegationRestrictionType;
import org.opensaml.saml.saml2.core.Action;
import org.opensaml.saml.saml2.core.Advice;
import org.opensaml.saml.saml2.core.Assertion;
import org.opensaml.saml.saml2.core.AssertionIDRef;
import org.opensaml.saml.saml2.core.AssertionURIRef;
import org.opensaml.saml.saml2.core.Attribute;
import org.opensaml.saml.saml2.core.AttributeStatement;
import org.opensaml.saml.saml2.core.AttributeValue;
import org.opensaml.saml.saml2.core.Audience;
import org.opensaml.saml.saml2.core.AudienceRestriction;
import org.opensaml.saml.saml2.core.AuthnContext;
import org.opensaml.saml.saml2.core.AuthnContextClassRef;
import org.opensaml.saml.saml2.core.AuthnStatement;
import org.opensaml.saml.saml2.core.AuthzDecisionStatement;
import org.opensaml.saml.saml2.core.Conditions;
import org.opensaml.saml.saml2.core.DecisionTypeEnumeration;
import org.opensaml.saml.saml2.core.Evidence;
import org.opensaml.saml.saml2.core.Issuer;
import org.opensaml.saml.saml2.core.KeyInfoConfirmationDataType;
import org.opensaml.saml.saml2.core.NameID;
import org.opensaml.saml.saml2.core.OneTimeUse;
import org.opensaml.saml.saml2.core.ProxyRestriction;
import org.opensaml.saml.saml2.core.Subject;
import org.opensaml.saml.saml2.core.SubjectConfirmation;
import org.opensaml.saml.saml2.core.SubjectConfirmationData;
import org.opensaml.saml.saml2.core.SubjectLocality;
import org.opensaml.xmlsec.signature.KeyInfo;
import org.w3c.dom.Element;
/**
* Class SAML2ComponentBuilder provides builder methods that can be used
* to construct SAML v2.0 statements using the OpenSaml library.
*/
public final class SAML2ComponentBuilder {
private static final transient org.slf4j.Logger LOG =
org.slf4j.LoggerFactory.getLogger(SAML2ComponentBuilder.class);
private static volatile SAMLObjectBuilder<Assertion> assertionBuilder;
private static volatile SAMLObjectBuilder<Issuer> issuerBuilder;
private static volatile SAMLObjectBuilder<Subject> subjectBuilder;
private static volatile SAMLObjectBuilder<NameID> nameIdBuilder;
private static volatile SAMLObjectBuilder<SubjectConfirmation> subjectConfirmationBuilder;
private static volatile SAMLObjectBuilder<OneTimeUse> oneTimeUseBuilder;
private static volatile SAMLObjectBuilder<ProxyRestriction> proxyRestrictionBuilder;
private static volatile SAMLObjectBuilder<Conditions> conditionsBuilder;
private static volatile SAMLObjectBuilder<Advice> adviceBuilder;
private static volatile SAMLObjectBuilder<AssertionIDRef> assertionIDRefBuilder;
private static volatile SAMLObjectBuilder<AssertionURIRef> assertionURIRefBuilder;
private static volatile SAMLObjectBuilder<SubjectConfirmationData> subjectConfirmationDataBuilder;
private static volatile SAMLObjectBuilder<KeyInfoConfirmationDataType> keyInfoConfirmationDataBuilder;
private static volatile SAMLObjectBuilder<AuthnStatement> authnStatementBuilder;
private static volatile SAMLObjectBuilder<AuthnContext> authnContextBuilder;
private static volatile SAMLObjectBuilder<AuthnContextClassRef> authnContextClassRefBuilder;
private static volatile SAMLObjectBuilder<AttributeStatement> attributeStatementBuilder;
private static volatile SAMLObjectBuilder<Attribute> attributeBuilder;
private static volatile XSStringBuilder stringBuilder;
private static volatile SAMLObjectBuilder<AudienceRestriction> audienceRestrictionBuilder;
private static volatile SAMLObjectBuilder<DelegationRestrictionType> delegationRestrictionBuilder;
private static volatile SAMLObjectBuilder<Audience> audienceBuilder;
private static volatile SAMLObjectBuilder<Delegate> delegateBuilder;
private static volatile SAMLObjectBuilder<AuthzDecisionStatement> authorizationDecisionStatementBuilder;
private static volatile SAMLObjectBuilder<Action> actionElementBuilder;
private static volatile XMLObjectBuilderFactory builderFactory =
XMLObjectProviderRegistrySupport.getBuilderFactory();
private static volatile SAMLObjectBuilder<SubjectLocality> subjectLocalityBuilder;
private SAML2ComponentBuilder() {
// Complete
}
/**
* Create a SAML 2 assertion
*
* @return a SAML 2 assertion
*/
@SuppressWarnings("unchecked")
public static Assertion createAssertion() {
if (assertionBuilder == null) {
assertionBuilder = (SAMLObjectBuilder<Assertion>)
builderFactory.getBuilder(Assertion.DEFAULT_ELEMENT_NAME);
if (assertionBuilder == null) {
throw new IllegalStateException(
"OpenSaml engine not initialized. Please make sure to initialize the OpenSaml engine "
+ "prior using it"
);
}
}
Assertion assertion =
assertionBuilder.buildObject(Assertion.DEFAULT_ELEMENT_NAME, Assertion.TYPE_NAME);
assertion.setID(IDGenerator.generateID("_"));
assertion.setVersion(SAMLVersion.VERSION_20);
assertion.setIssueInstant(Instant.now());
return assertion;
}
/**
* Create an Issuer object
*
* @param issuerValue of type String
* @param issuerFormat of type String
* @param issuerQualifier of type String
* @return an Issuer object
*/
@SuppressWarnings("unchecked")
public static Issuer createIssuer(String issuerValue, String issuerFormat, String issuerQualifier) {
if (issuerBuilder == null) {
issuerBuilder = (SAMLObjectBuilder<Issuer>)
builderFactory.getBuilder(Issuer.DEFAULT_ELEMENT_NAME);
}
Issuer issuer = issuerBuilder.buildObject();
//
// The SAML authority that is making the claim(s) in the assertion. The issuer SHOULD
// be unambiguous to the intended relying parties.
issuer.setValue(issuerValue);
issuer.setFormat(issuerFormat);
issuer.setNameQualifier(issuerQualifier);
return issuer;
}
/**
* Create a Conditions object
*
* @param conditionsBean A ConditionsBean object
* @return a Conditions object
*/
@SuppressWarnings("unchecked")
public static Conditions createConditions(ConditionsBean conditionsBean) {
if (conditionsBuilder == null) {
conditionsBuilder = (SAMLObjectBuilder<Conditions>)
builderFactory.getBuilder(Conditions.DEFAULT_ELEMENT_NAME);
}
Conditions conditions = conditionsBuilder.buildObject();
if (conditionsBean == null) {
Instant newNotBefore = Instant.now();
conditions.setNotBefore(newNotBefore);
conditions.setNotOnOrAfter(newNotBefore.plus(Duration.ofMinutes(5)));
return conditions;
}
long tokenPeriodSeconds = conditionsBean.getTokenPeriodSeconds();
Instant notBefore = conditionsBean.getNotBefore();
Instant notAfter = conditionsBean.getNotAfter();
if (notBefore != null && notAfter != null) {
if (notBefore.isAfter(notAfter)) {
throw new IllegalStateException(
"The value of notBefore may not be after the value of notAfter"
);
}
conditions.setNotBefore(notBefore);
conditions.setNotOnOrAfter(notAfter);
} else {
Instant newNotBefore = Instant.now();
conditions.setNotBefore(newNotBefore);
if (tokenPeriodSeconds <= 0) {
tokenPeriodSeconds = 5L * 60L;
}
Instant notOnOrAfter = newNotBefore.plusSeconds(tokenPeriodSeconds);
conditions.setNotOnOrAfter(notOnOrAfter);
}
if (conditionsBean.getAudienceRestrictions() != null
&& !conditionsBean.getAudienceRestrictions().isEmpty()) {
for (AudienceRestrictionBean audienceRestrictionBean
: conditionsBean.getAudienceRestrictions()) {
AudienceRestriction audienceRestriction =
createAudienceRestriction(audienceRestrictionBean);
conditions.getAudienceRestrictions().add(audienceRestriction);
}
}
if (conditionsBean.isOneTimeUse()) {
conditions.getConditions().add(createOneTimeUse());
}
if (conditionsBean.getProxyRestriction() != null) {
conditions.getConditions().add(createProxyRestriction(conditionsBean.getProxyRestriction()));
}
if (conditionsBean.getDelegates() != null && !conditionsBean.getDelegates().isEmpty()) {
DelegationRestrictionType delegationRestriction =
createDelegationRestriction(conditionsBean.getDelegates());
conditions.getConditions().add(delegationRestriction);
}
return conditions;
}
/**
* Create a Advice object
*
* @param adviceBean A AdviceBean object
* @return a Advice object
* @throws WSSecurityException
*/
@SuppressWarnings("unchecked")
public static Advice createAdvice(AdviceBean adviceBean) throws WSSecurityException {
if (adviceBuilder == null) {
adviceBuilder = (SAMLObjectBuilder<Advice>)
builderFactory.getBuilder(Advice.DEFAULT_ELEMENT_NAME);
}
Advice advice = adviceBuilder.buildObject();
if (!adviceBean.getIdReferences().isEmpty()) {
if (assertionIDRefBuilder == null) {
assertionIDRefBuilder = (SAMLObjectBuilder<AssertionIDRef>)
builderFactory.getBuilder(AssertionIDRef.DEFAULT_ELEMENT_NAME);
}
for (String ref : adviceBean.getIdReferences()) {
AssertionIDRef assertionIdRef = assertionIDRefBuilder.buildObject();
assertionIdRef.setAssertionID(ref);
advice.getAssertionIDReferences().add(assertionIdRef);
}
}
if (!adviceBean.getUriReferences().isEmpty()) {
if (assertionURIRefBuilder == null) {
assertionURIRefBuilder = (SAMLObjectBuilder<AssertionURIRef>)
builderFactory.getBuilder(AssertionURIRef.DEFAULT_ELEMENT_NAME);
}
for (String ref : adviceBean.getUriReferences()) {
AssertionURIRef assertionURIRef = assertionURIRefBuilder.buildObject();
assertionURIRef.setAssertionURI(ref);
advice.getAssertionURIReferences().add(assertionURIRef);
}
}
if (!adviceBean.getAssertions().isEmpty()) {
for (Element assertionElement : adviceBean.getAssertions()) {
XMLObject xmlObject = OpenSAMLUtil.fromDom(assertionElement);
if (xmlObject instanceof Assertion) {
Assertion assertion = (Assertion)xmlObject;
advice.getAssertions().add(assertion);
}
}
}
return advice;
}
/**
* Create an AudienceRestriction object
*
* @param audienceRestrictionBean of type AudienceRestrictionBean
* @return an AudienceRestriction object
*/
@SuppressWarnings("unchecked")
public static AudienceRestriction createAudienceRestriction(
AudienceRestrictionBean audienceRestrictionBean
) {
if (audienceRestrictionBuilder == null) {
audienceRestrictionBuilder = (SAMLObjectBuilder<AudienceRestriction>)
builderFactory.getBuilder(AudienceRestriction.DEFAULT_ELEMENT_NAME);
}
if (audienceBuilder == null) {
audienceBuilder = (SAMLObjectBuilder<Audience>)
builderFactory.getBuilder(Audience.DEFAULT_ELEMENT_NAME);
}
AudienceRestriction audienceRestriction = audienceRestrictionBuilder.buildObject();
for (String audienceURI : audienceRestrictionBean.getAudienceURIs()) {
Audience audience = audienceBuilder.buildObject();
audience.setAudienceURI(audienceURI);
audienceRestriction.getAudiences().add(audience);
}
return audienceRestriction;
}
/**
* Create an DelegationRestrictionType object
*
* @param delegates of type List<DelegateBean>
* @return a DelegationRestrictionType object
*/
@SuppressWarnings("unchecked")
public static DelegationRestrictionType createDelegationRestriction(
List<DelegateBean> delegates
) {
if (delegationRestrictionBuilder == null) {
delegationRestrictionBuilder = (SAMLObjectBuilder<DelegationRestrictionType>)
builderFactory.getBuilder(DelegationRestrictionType.TYPE_NAME);
}
DelegationRestrictionType delegationRestriction = delegationRestrictionBuilder.buildObject();
if (delegateBuilder == null) {
delegateBuilder = (SAMLObjectBuilder<Delegate>)
builderFactory.getBuilder(Delegate.DEFAULT_ELEMENT_NAME);
}
for (DelegateBean delegateBean : delegates) {
Delegate delegate = delegateBuilder.buildObject();
delegate.setConfirmationMethod(delegateBean.getConfirmationMethod());
delegate.setDelegationInstant(delegateBean.getDelegationInstant());
if (delegateBean.getNameIDBean() == null) {
throw new IllegalStateException(
"The value of NameIDBean in DelegateBean may not be null"
);
}
NameID nameID = createNameID(delegateBean.getNameIDBean());
delegate.setNameID(nameID);
delegationRestriction.getDelegates().add(delegate);
}
return delegationRestriction;
}
/**
* Create a OneTimeUse object
*
* @return a OneTimeUse object
*/
@SuppressWarnings("unchecked")
public static OneTimeUse createOneTimeUse() {
if (oneTimeUseBuilder == null) {
oneTimeUseBuilder = (SAMLObjectBuilder<OneTimeUse>)
builderFactory.getBuilder(OneTimeUse.DEFAULT_ELEMENT_NAME);
}
return oneTimeUseBuilder.buildObject();
}
/**
* Create a ProxyRestriction object
*
* @return a ProxyRestriction object
*/
@SuppressWarnings("unchecked")
public static ProxyRestriction createProxyRestriction(ProxyRestrictionBean proxyRestrictionBean) {
if (proxyRestrictionBuilder == null) {
proxyRestrictionBuilder = (SAMLObjectBuilder<ProxyRestriction>)
builderFactory.getBuilder(ProxyRestriction.DEFAULT_ELEMENT_NAME);
}
ProxyRestriction proxyRestriction = proxyRestrictionBuilder.buildObject();
if (proxyRestrictionBean.getCount() > 0) {
proxyRestriction.setProxyCount(proxyRestrictionBean.getCount());
}
if (!proxyRestrictionBean.getAudienceURIs().isEmpty()) {
if (audienceBuilder == null) {
audienceBuilder = (SAMLObjectBuilder<Audience>)
builderFactory.getBuilder(Audience.DEFAULT_ELEMENT_NAME);
}
for (String audienceURI : proxyRestrictionBean.getAudienceURIs()) {
Audience audience = audienceBuilder.buildObject();
audience.setAudienceURI(audienceURI);
proxyRestriction.getAudiences().add(audience);
}
}
return proxyRestriction;
}
/**
* Create SAML 2 Authentication Statement(s).
*
* @param authBeans A list of AuthenticationStatementBean instances
* @return SAML 2 Authentication Statement(s).
*/
@SuppressWarnings("unchecked")
public static List<AuthnStatement> createAuthnStatement(
List<AuthenticationStatementBean> authBeans
) {
List<AuthnStatement> authnStatements = new ArrayList<>();
if (authnStatementBuilder == null) {
authnStatementBuilder = (SAMLObjectBuilder<AuthnStatement>)
builderFactory.getBuilder(AuthnStatement.DEFAULT_ELEMENT_NAME);
}
if (authnContextBuilder == null) {
authnContextBuilder = (SAMLObjectBuilder<AuthnContext>)
builderFactory.getBuilder(AuthnContext.DEFAULT_ELEMENT_NAME);
}
if (authnContextClassRefBuilder == null) {
authnContextClassRefBuilder = (SAMLObjectBuilder<AuthnContextClassRef>)
builderFactory.getBuilder(AuthnContextClassRef.DEFAULT_ELEMENT_NAME);
}
if (subjectLocalityBuilder == null) {
subjectLocalityBuilder = (SAMLObjectBuilder<SubjectLocality>)
builderFactory.getBuilder(SubjectLocality.DEFAULT_ELEMENT_NAME);
}
if (authBeans != null && !authBeans.isEmpty()) {
for (AuthenticationStatementBean statementBean : authBeans) {
AuthnStatement authnStatement = authnStatementBuilder.buildObject();
Instant authInstant = statementBean.getAuthenticationInstant();
if (authInstant == null) {
authInstant = Instant.now();
}
authnStatement.setAuthnInstant(authInstant);
Instant sessionNotOnOrAfter = statementBean.getSessionNotOnOrAfter();
if (sessionNotOnOrAfter != null) {
authnStatement.setSessionNotOnOrAfter(sessionNotOnOrAfter);
}
if (statementBean.getSessionIndex() != null) {
authnStatement.setSessionIndex(statementBean.getSessionIndex());
}
AuthnContextClassRef authnContextClassRef = authnContextClassRefBuilder.buildObject();
authnContextClassRef.setAuthnContextClassRef(
transformAuthenticationMethod(statementBean.getAuthenticationMethod())
);
AuthnContext authnContext = authnContextBuilder.buildObject();
authnContext.setAuthnContextClassRef(authnContextClassRef);
authnStatement.setAuthnContext(authnContext);
SubjectLocalityBean subjectLocalityBean = statementBean.getSubjectLocality();
if (subjectLocalityBean != null) {
SubjectLocality subjectLocality = subjectLocalityBuilder.buildObject();
subjectLocality.setDNSName(subjectLocalityBean.getDnsAddress());
subjectLocality.setAddress(subjectLocalityBean.getIpAddress());
authnStatement.setSubjectLocality(subjectLocality);
}
authnStatements.add(authnStatement);
}
}
return authnStatements;
}
/**
* Transform the user-supplied authentication method value into one of the supported
* specification-compliant values.
*
* @param sourceMethod of type String
* @return String
*/
private static String transformAuthenticationMethod(String sourceMethod) {
String transformedMethod = "";
if ("Password".equalsIgnoreCase(sourceMethod)) {
transformedMethod = SAML2Constants.AUTH_CONTEXT_CLASS_REF_PASSWORD;
} else if (sourceMethod != null && sourceMethod.length() != 0) {
return sourceMethod;
}
return transformedMethod;
}
/**
* Create a SAML2 Attribute
*
* @param friendlyName of type String
* @param name of type String
* @param nameFormat of type String
* @param values of type ArrayList
* @return a SAML2 Attribute
*/
public static Attribute createAttribute(
String friendlyName, String name, String nameFormat, List<Object> values
) {
if (stringBuilder == null) {
stringBuilder = (XSStringBuilder)builderFactory.getBuilder(XSString.TYPE_NAME);
}
Attribute attribute = createAttribute(friendlyName, name, nameFormat);
for (Object value : values) {
if (value instanceof String) {
XSString attributeValue =
stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME);
attributeValue.setValue((String)value);
attribute.getAttributeValues().add(attributeValue);
} else if (value instanceof XMLObject) {
attribute.getAttributeValues().add((XMLObject)value);
}
}
return attribute;
}
/**
* Create a Subject.
*
* @param subjectBean of type SubjectBean
* @return a Subject
*/
@SuppressWarnings("unchecked")
public static Subject createSaml2Subject(SubjectBean subjectBean)
throws org.opensaml.security.SecurityException, WSSecurityException {
if (subjectBuilder == null) {
subjectBuilder = (SAMLObjectBuilder<Subject>)
builderFactory.getBuilder(Subject.DEFAULT_ELEMENT_NAME);
}
Subject subject = subjectBuilder.buildObject();
NameID nameID = SAML2ComponentBuilder.createNameID(subjectBean);
subject.setNameID(nameID);
SubjectConfirmationData subjectConfData = null;
if (subjectBean.getKeyInfo() != null || subjectBean.getSubjectConfirmationData() != null) {
subjectConfData =
SAML2ComponentBuilder.createSubjectConfirmationData(
subjectBean.getSubjectConfirmationData(),
subjectBean.getKeyInfo()
);
}
NameID subjectConfNameId = null;
if (subjectBean.getSubjectConfirmationNameID() != null) {
subjectConfNameId = SAML2ComponentBuilder.createNameID(subjectBean.getSubjectConfirmationNameID());
}
String confirmationMethodStr = subjectBean.getSubjectConfirmationMethod();
if (confirmationMethodStr == null) {
confirmationMethodStr = SAML2Constants.CONF_SENDER_VOUCHES;
}
SubjectConfirmation subjectConfirmation =
SAML2ComponentBuilder.createSubjectConfirmation(
confirmationMethodStr, subjectConfData, subjectConfNameId
);
subject.getSubjectConfirmations().add(subjectConfirmation);
return subject;
}
/**
* Create a SubjectConfirmationData object
*
* @param subjectConfirmationDataBean of type SubjectConfirmationDataBean
* @param keyInfoBean of type KeyInfoBean
* @return a SubjectConfirmationData object
*/
@SuppressWarnings("unchecked")
public static SubjectConfirmationData createSubjectConfirmationData(
SubjectConfirmationDataBean subjectConfirmationDataBean,
KeyInfoBean keyInfoBean
) throws org.opensaml.security.SecurityException, WSSecurityException {
SubjectConfirmationData subjectConfirmationData = null;
KeyInfo keyInfo = null;
if (keyInfoBean == null) {
if (subjectConfirmationDataBuilder == null) {
subjectConfirmationDataBuilder = (SAMLObjectBuilder<SubjectConfirmationData>)
builderFactory.getBuilder(SubjectConfirmationData.DEFAULT_ELEMENT_NAME);
}
subjectConfirmationData = subjectConfirmationDataBuilder.buildObject();
} else {
if (keyInfoConfirmationDataBuilder == null) {
keyInfoConfirmationDataBuilder = (SAMLObjectBuilder<KeyInfoConfirmationDataType>)
builderFactory.getBuilder(KeyInfoConfirmationDataType.TYPE_NAME);
}
subjectConfirmationData = keyInfoConfirmationDataBuilder.buildObject();
keyInfo = SAML1ComponentBuilder.createKeyInfo(keyInfoBean);
((KeyInfoConfirmationDataType)subjectConfirmationData).getKeyInfos().add(keyInfo);
}
if (subjectConfirmationDataBean != null) {
if (subjectConfirmationDataBean.getInResponseTo() != null) {
subjectConfirmationData.setInResponseTo(subjectConfirmationDataBean.getInResponseTo());
}
if (subjectConfirmationDataBean.getRecipient() != null) {
subjectConfirmationData.setRecipient(subjectConfirmationDataBean.getRecipient());
}
if (subjectConfirmationDataBean.getAddress() != null) {
subjectConfirmationData.setAddress(subjectConfirmationDataBean.getAddress());
}
if (subjectConfirmationDataBean.getNotAfter() != null) {
subjectConfirmationData.setNotOnOrAfter(subjectConfirmationDataBean.getNotAfter());
}
if (subjectConfirmationDataBean.getNotBefore() != null) {
subjectConfirmationData.setNotBefore(subjectConfirmationDataBean.getNotBefore());
}
if (subjectConfirmationDataBean.getAny() != null) {
List<XMLObject> unknownObjects = subjectConfirmationData.getUnknownXMLObjects();
for (Object obj : subjectConfirmationDataBean.getAny()) {
if (obj == null) {
LOG.warn("Ignore <null> object in SubjectConfirmationData.any");
} else if (obj instanceof XMLObject) {
unknownObjects.add((XMLObject) obj);
} else if (obj instanceof AttributeStatementBean) {
unknownObjects.addAll(createAttributeStatement(Collections.singletonList((AttributeStatementBean) obj)));
} else {
LOG.warn("Ignore object of the unsupported type {} in SubjectConfirmationData.any", obj.getClass());
}
}
}
}
return subjectConfirmationData;
}
/**
* Create a SubjectConfirmation object
* One of the following subject confirmation methods MUST be used:
* urn:oasis:names:tc:SAML:2.0:cm:holder-of-key
* urn:oasis:names:tc:SAML:2.0:cm:sender-vouches
* urn:oasis:names:tc:SAML:2.0:cm:bearer
*
* @param method of type String
* @param subjectConfirmationData of type SubjectConfirmationData
* @return a SubjectConfirmation object
*/
@SuppressWarnings("unchecked")
public static SubjectConfirmation createSubjectConfirmation(
String method,
SubjectConfirmationData subjectConfirmationData,
NameID subjectConfirmationNameId
) {
if (subjectConfirmationBuilder == null) {
subjectConfirmationBuilder = (SAMLObjectBuilder<SubjectConfirmation>)
builderFactory.getBuilder(SubjectConfirmation.DEFAULT_ELEMENT_NAME);
}
SubjectConfirmation subjectConfirmation = subjectConfirmationBuilder.buildObject();
subjectConfirmation.setMethod(method);
subjectConfirmation.setSubjectConfirmationData(subjectConfirmationData);
subjectConfirmation.setNameID(subjectConfirmationNameId);
return subjectConfirmation;
}
/**
* Create a NameID object
* One of the following formats MUST be used:
* urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
* urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
* urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName
* urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName
* urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos
* urn:oasis:names:tc:SAML:2.0:nameid-format:entity
* urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
* urn:oasis:names:tc:SAML:2.0:nameid-format:transient
*
* @param subject A SubjectBean instance
* @return NameID
*/
public static NameID createNameID(SubjectBean subject) {
NameIDBean nameIDBean = new NameIDBean();
nameIDBean.setNameIDFormat(subject.getSubjectNameIDFormat());
nameIDBean.setNameQualifier(subject.getSubjectNameQualifier());
nameIDBean.setSPNameQualifier(subject.getSubjectNameSPNameQualifier());
nameIDBean.setSPProvidedID(subject.getSubjectNameSPProvidedID());
nameIDBean.setNameValue(subject.getSubjectName());
return createNameID(nameIDBean);
}
@SuppressWarnings("unchecked")
public static NameID createNameID(NameIDBean nameIDBean) {
if (nameIdBuilder == null) {
nameIdBuilder = (SAMLObjectBuilder<NameID>)
builderFactory.getBuilder(NameID.DEFAULT_ELEMENT_NAME);
}
NameID nameID = nameIdBuilder.buildObject();
nameID.setNameQualifier(nameIDBean.getNameQualifier());
nameID.setFormat(nameIDBean.getNameIDFormat());
nameID.setValue(nameIDBean.getNameValue());
nameID.setSPNameQualifier(nameIDBean.getSPNameQualifier());
nameID.setSPProvidedID(nameIDBean.getSPProvidedID());
return nameID;
}
/**
* Create SAML2 Attribute Statement(s)
*
* @param attributeData A list of AttributeStatementBean instances
* @return SAML2 Attribute Statement(s)
*/
@SuppressWarnings("unchecked")
public static List<AttributeStatement> createAttributeStatement(
List<AttributeStatementBean> attributeData
) {
List<AttributeStatement> attributeStatements = new ArrayList<>();
if (attributeStatementBuilder == null) {
attributeStatementBuilder = (SAMLObjectBuilder<AttributeStatement>)
builderFactory.getBuilder(AttributeStatement.DEFAULT_ELEMENT_NAME);
}
if (attributeData != null && !attributeData.isEmpty()) {
for (AttributeStatementBean statementBean : attributeData) {
AttributeStatement attributeStatement = attributeStatementBuilder.buildObject();
for (AttributeBean values : statementBean.getSamlAttributes()) {
List<Object> attributeValues = values.getAttributeValues();
Attribute samlAttribute =
createAttribute(
values.getSimpleName(),
values.getQualifiedName(),
values.getNameFormat(),
attributeValues
);
attributeStatement.getAttributes().add(samlAttribute);
}
// Add the completed attribute statementBean to the collection
attributeStatements.add(attributeStatement);
}
}
return attributeStatements;
}
/**
* Create an Attribute object.
*
* @param friendlyName of type String
* @param name of type String
* @param nameFormat of type String
* @return an Attribute object
*/
@SuppressWarnings("unchecked")
public static Attribute createAttribute(String friendlyName, String name, String nameFormat) {
if (attributeBuilder == null) {
attributeBuilder = (SAMLObjectBuilder<Attribute>)
builderFactory.getBuilder(Attribute.DEFAULT_ELEMENT_NAME);
}
Attribute attribute = attributeBuilder.buildObject();
attribute.setFriendlyName(friendlyName);
if (nameFormat == null) {
attribute.setNameFormat(SAML2Constants.ATTRNAME_FORMAT_URI);
} else {
attribute.setNameFormat(nameFormat);
}
attribute.setName(name);
return attribute;
}
/**
* Create SAML2 AuthorizationDecisionStatement(s)
*
* @param decisionData A list of AuthDecisionStatementBean instances
* @return SAML2 AuthorizationDecisionStatement(s)
*/
@SuppressWarnings("unchecked")
public static List<AuthzDecisionStatement> createAuthorizationDecisionStatement(
List<AuthDecisionStatementBean> decisionData
) {
List<AuthzDecisionStatement> authDecisionStatements = new ArrayList<>();
if (authorizationDecisionStatementBuilder == null) {
authorizationDecisionStatementBuilder =
(SAMLObjectBuilder<AuthzDecisionStatement>)
builderFactory.getBuilder(AuthzDecisionStatement.DEFAULT_ELEMENT_NAME);
}
if (decisionData != null && !decisionData.isEmpty()) {
for (AuthDecisionStatementBean decisionStatementBean : decisionData) {
AuthzDecisionStatement authDecision =
authorizationDecisionStatementBuilder.buildObject();
authDecision.setResource(decisionStatementBean.getResource());
authDecision.setDecision(
transformDecisionType(decisionStatementBean.getDecision())
);
for (ActionBean actionBean : decisionStatementBean.getActions()) {
Action actionElement = createSamlAction(actionBean);
authDecision.getActions().add(actionElement);
}
if (decisionStatementBean.getEvidence() instanceof Evidence) {
authDecision.setEvidence((Evidence)decisionStatementBean.getEvidence());
}
authDecisionStatements.add(authDecision);
}
}
return authDecisionStatements;
}
/**
* Create an Action object
*
* @param actionBean An ActionBean instance
* @return an Action object
*/
@SuppressWarnings("unchecked")
public static Action createSamlAction(ActionBean actionBean) {
if (actionElementBuilder == null) {
actionElementBuilder = (SAMLObjectBuilder<Action>)
builderFactory.getBuilder(Action.DEFAULT_ELEMENT_NAME);
}
Action actionElement = actionElementBuilder.buildObject();
actionElement.setNamespace(actionBean.getActionNamespace());
if (actionBean.getActionNamespace() == null) {
actionElement.setNamespace("urn:oasis:names:tc:SAML:1.0:action:rwedc-negation");
}
actionElement.setAction(actionBean.getContents());
return actionElement;
}
/**
* Create a DecisionTypeEnumeration object
*
* @param decision of type Decision
* @return a DecisionTypeEnumeration object
*/
private static DecisionTypeEnumeration transformDecisionType(
AuthDecisionStatementBean.Decision decision
) {
DecisionTypeEnumeration decisionTypeEnum = DecisionTypeEnumeration.DENY;
if (decision.equals(AuthDecisionStatementBean.Decision.PERMIT)) {
decisionTypeEnum = DecisionTypeEnumeration.PERMIT;
} else if (decision.equals(AuthDecisionStatementBean.Decision.INDETERMINATE)) {
decisionTypeEnum = DecisionTypeEnumeration.INDETERMINATE;
}
return decisionTypeEnum;
}
}