package org.apereo.cas.support.saml.web.idp.profile.builders.response;
import com.google.common.base.Throwables;
import org.apereo.cas.support.saml.OpenSamlConfigBean;
import org.apereo.cas.support.saml.SamlException;
import org.apereo.cas.support.saml.SamlUtils;
import org.apereo.cas.support.saml.services.SamlRegisteredService;
import org.apereo.cas.support.saml.services.idp.metadata.SamlRegisteredServiceServiceProviderMetadataFacade;
import org.apereo.cas.support.saml.web.idp.profile.builders.SamlProfileObjectBuilder;
import org.apereo.cas.support.saml.web.idp.profile.builders.enc.BaseSamlObjectSigner;
import org.apereo.cas.support.saml.web.idp.profile.builders.enc.SamlObjectEncrypter;
import org.opensaml.messaging.context.MessageContext;
import org.opensaml.saml.common.SAMLObject;
import org.opensaml.saml.common.xml.SAMLConstants;
import org.opensaml.saml.saml2.binding.encoding.impl.HTTPSOAP11Encoder;
import org.opensaml.saml.saml2.core.Assertion;
import org.opensaml.saml.saml2.core.AuthnRequest;
import org.opensaml.saml.saml2.ecp.Response;
import org.opensaml.saml.saml2.metadata.AssertionConsumerService;
import org.opensaml.soap.messaging.context.SOAP11Context;
import org.opensaml.soap.soap11.Body;
import org.opensaml.soap.soap11.Envelope;
import org.opensaml.soap.soap11.Header;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ui.velocity.VelocityEngineFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* The {@link SamlProfileSamlSoap11ResponseBuilder} is responsible for
* building the final SAML assertion for the relying party.
*
* @author Misagh Moayyed
* @since 4.2
*/
public class SamlProfileSamlSoap11ResponseBuilder extends BaseSamlProfileSamlResponseBuilder<Envelope> {
private static final Logger LOGGER = LoggerFactory.getLogger(SamlProfileSamlSoap11ResponseBuilder.class);
private static final long serialVersionUID = -1875903354216171261L;
private final SamlProfileObjectBuilder<? extends SAMLObject> saml2ResponseBuilder;
public SamlProfileSamlSoap11ResponseBuilder(
final OpenSamlConfigBean openSamlConfigBean,
final BaseSamlObjectSigner samlObjectSigner,
final VelocityEngineFactory velocityEngineFactory,
final SamlProfileObjectBuilder<Assertion> samlProfileSamlAssertionBuilder,
final SamlProfileObjectBuilder<? extends SAMLObject> saml2ResponseBuilder,
final SamlObjectEncrypter samlObjectEncrypter) {
super(openSamlConfigBean, samlObjectSigner, velocityEngineFactory, samlProfileSamlAssertionBuilder, samlObjectEncrypter);
this.saml2ResponseBuilder = saml2ResponseBuilder;
}
@Override
protected Envelope buildResponse(final Assertion assertion,
final org.jasig.cas.client.validation.Assertion casAssertion,
final AuthnRequest authnRequest,
final SamlRegisteredService service,
final SamlRegisteredServiceServiceProviderMetadataFacade adaptor,
final HttpServletRequest request,
final HttpServletResponse response,
final String binding) throws SamlException {
final AssertionConsumerService acs = adaptor.getAssertionConsumerService(binding);
if (acs == null) {
LOGGER.warn("Could not locate the assertion consumer service url for binding [{}]", SAMLConstants.SAML2_PAOS_BINDING_URI);
throw new IllegalArgumentException("Failed to locate the assertion consumer service url for ECP");
}
LOGGER.debug("Located assertion consumer service url [{}]", acs);
final Response ecpResponse = newEcpResponse(acs.getLocation());
final Header header = newSoapObject(Header.class);
header.getUnknownXMLObjects().add(ecpResponse);
final Body body = newSoapObject(Body.class);
final org.opensaml.saml.saml2.core.Response saml2Response =
buildSaml2Response(casAssertion, authnRequest, service, adaptor, request, binding);
body.getUnknownXMLObjects().add(saml2Response);
final Envelope envelope = newSoapObject(Envelope.class);
envelope.setHeader(header);
envelope.setBody(body);
SamlUtils.logSamlObject(this.configBean, envelope);
return envelope;
}
private org.opensaml.saml.saml2.core.Response buildSaml2Response(final org.jasig.cas.client.validation.Assertion casAssertion,
final AuthnRequest authnRequest, final SamlRegisteredService service,
final SamlRegisteredServiceServiceProviderMetadataFacade adaptor,
final HttpServletRequest request,
final String binding) {
return (org.opensaml.saml.saml2.core.Response)
saml2ResponseBuilder.build(authnRequest, request, null,
casAssertion, service, adaptor, binding);
}
@Override
protected Envelope encode(final SamlRegisteredService service,
final Envelope envelope,
final HttpServletResponse httpResponse,
final SamlRegisteredServiceServiceProviderMetadataFacade adaptor,
final String relayState,
final String binding) throws SamlException {
try {
final MessageContext result = new MessageContext();
final SOAP11Context ctx = result.getSubcontext(SOAP11Context.class, true);
ctx.setEnvelope(envelope);
final HTTPSOAP11Encoder encoder = new HTTPSOAP11Encoder();
encoder.setHttpServletResponse(httpResponse);
encoder.setMessageContext(result);
encoder.initialize();
encoder.encode();
} catch (final Exception e) {
throw Throwables.propagate(e);
}
return envelope;
}
}