package org.apereo.cas.support.saml.web.idp.profile.builders;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.support.saml.OpenSamlConfigBean;
import org.apereo.cas.support.saml.SamlException;
import org.apereo.cas.support.saml.services.SamlRegisteredService;
import org.apereo.cas.support.saml.services.idp.metadata.SamlRegisteredServiceServiceProviderMetadataFacade;
import org.apereo.cas.support.saml.util.AbstractSaml20ObjectBuilder;
import org.apereo.cas.support.saml.web.idp.profile.builders.enc.BaseSamlObjectSigner;
import org.opensaml.saml.saml2.core.Assertion;
import org.opensaml.saml.saml2.core.AttributeStatement;
import org.opensaml.saml.saml2.core.AuthnRequest;
import org.opensaml.saml.saml2.core.AuthnStatement;
import org.opensaml.saml.saml2.core.Conditions;
import org.opensaml.saml.saml2.core.Statement;
import org.opensaml.saml.saml2.core.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.security.SecureRandom;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;
/**
* This is {@link SamlProfileSamlAssertionBuilder}.
*
* @author Misagh Moayyed
* @since 5.0.0
*/
public class SamlProfileSamlAssertionBuilder extends AbstractSaml20ObjectBuilder implements SamlProfileObjectBuilder<Assertion> {
private static final long serialVersionUID = -3945938960014421135L;
private static final Logger LOGGER = LoggerFactory.getLogger(SamlProfileSamlAssertionBuilder.class);
@Autowired
private CasConfigurationProperties casProperties;
private SamlProfileObjectBuilder<AuthnStatement> samlProfileSamlAuthNStatementBuilder;
private SamlProfileObjectBuilder<AttributeStatement> samlProfileSamlAttributeStatementBuilder;
private SamlProfileObjectBuilder<Subject> samlProfileSamlSubjectBuilder;
private SamlProfileObjectBuilder<Conditions> samlProfileSamlConditionsBuilder;
private BaseSamlObjectSigner samlObjectSigner;
public SamlProfileSamlAssertionBuilder(final OpenSamlConfigBean configBean,
final SamlProfileObjectBuilder<AuthnStatement> samlProfileSamlAuthNStatementBuilder,
final SamlProfileObjectBuilder<AttributeStatement> samlProfileSamlAttributeStatementBuilder,
final SamlProfileObjectBuilder<Subject> samlProfileSamlSubjectBuilder,
final SamlProfileObjectBuilder<Conditions> samlProfileSamlConditionsBuilder,
final BaseSamlObjectSigner samlObjectSigner) {
super(configBean);
this.samlProfileSamlAuthNStatementBuilder = samlProfileSamlAuthNStatementBuilder;
this.samlProfileSamlAttributeStatementBuilder = samlProfileSamlAttributeStatementBuilder;
this.samlProfileSamlSubjectBuilder = samlProfileSamlSubjectBuilder;
this.samlProfileSamlConditionsBuilder = samlProfileSamlConditionsBuilder;
this.samlObjectSigner = samlObjectSigner;
}
@Override
public Assertion build(final AuthnRequest authnRequest, final HttpServletRequest request, final HttpServletResponse response,
final org.jasig.cas.client.validation.Assertion casAssertion, final SamlRegisteredService service,
final SamlRegisteredServiceServiceProviderMetadataFacade adaptor,
final String binding) throws SamlException {
final List<Statement> statements = new ArrayList<>();
statements.add(this.samlProfileSamlAuthNStatementBuilder.build(authnRequest, request, response,
casAssertion, service, adaptor, binding));
statements.add(this.samlProfileSamlAttributeStatementBuilder.build(authnRequest, request,
response, casAssertion, service, adaptor, binding));
final String id = '_' + String.valueOf(Math.abs(new SecureRandom().nextLong()));
final Assertion assertion = newAssertion(statements, casProperties.getAuthn().getSamlIdp().getEntityId(),
ZonedDateTime.now(ZoneOffset.UTC), id);
assertion.setSubject(this.samlProfileSamlSubjectBuilder.build(authnRequest, request, response,
casAssertion, service, adaptor, binding));
assertion.setConditions(this.samlProfileSamlConditionsBuilder.build(authnRequest,
request, response, casAssertion, service, adaptor, binding));
signAssertion(assertion, request, response, service, adaptor, binding);
return assertion;
}
/**
* Sign assertion.
*
* @param assertion the assertion
* @param request the request
* @param response the response
* @param service the service
* @param adaptor the adaptor
* @param binding the binding
* @throws SamlException the saml exception
*/
protected void signAssertion(final Assertion assertion,
final HttpServletRequest request, final HttpServletResponse response,
final SamlRegisteredService service,
final SamlRegisteredServiceServiceProviderMetadataFacade adaptor,
final String binding) throws SamlException {
try {
if (service.isSignAssertions()) {
LOGGER.debug("SAML registered service [{}] requires assertions to be signed", adaptor.getEntityId());
this.samlObjectSigner.encode(assertion, service, adaptor,
response, request, binding);
} else {
LOGGER.debug("SAML registered service [{}] does not require assertions to be signed", adaptor.getEntityId());
}
} catch (final Exception e) {
throw new SamlException("Unable to marshall assertion for signing", e);
}
}
}