package org.atricore.idbus.capabilities.oauth2.main.sso.producers; import org.apache.camel.Endpoint; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.atricore.idbus.capabilities.oauth2.main.OAuth2AuthnContext; import org.atricore.idbus.capabilities.oauth2.main.OAuth2BPMediator; import org.atricore.idbus.capabilities.oauth2.main.OAuth2Exception; import org.atricore.idbus.capabilities.oauth2.main.ResourceServer; import org.atricore.idbus.capabilities.oauth2.main.binding.OAuth2Binding; import org.atricore.idbus.capabilities.sts.main.WSTConstants; import org.atricore.idbus.common.sso._1_0.protocol.*; import org.atricore.idbus.kernel.main.federation.metadata.EndpointDescriptor; import org.atricore.idbus.kernel.main.federation.metadata.EndpointDescriptorImpl; import org.atricore.idbus.kernel.main.mediation.MediationMessageImpl; import org.atricore.idbus.kernel.main.mediation.MediationState; import org.atricore.idbus.kernel.main.mediation.camel.AbstractCamelProducer; import org.atricore.idbus.kernel.main.mediation.camel.component.binding.CamelMediationExchange; import org.atricore.idbus.kernel.main.mediation.camel.component.binding.CamelMediationMessage; import java.net.URLEncoder; /** * @author <a href=mailto:sgonzalez@atricore.org>Sebastian Gonzalez Oyuela</a> */ public class AssertionConsumerProducer extends AbstractCamelProducer<CamelMediationExchange> { private static final Log logger = LogFactory.getLog(AssertionConsumerProducer.class); public AssertionConsumerProducer(Endpoint endpoint) { super(endpoint); } @Override protected void doProcess(CamelMediationExchange exchange) throws Exception { CamelMediationMessage in = (CamelMediationMessage) exchange.getIn(); MediationState state = in.getMessage().getState(); SPAuthnResponseType response = (SPAuthnResponseType) in.getMessage().getContent(); // TODO : Add support for IDP initiated SSO in OAUTH2 OAuth2AuthnContext authnCtx = (OAuth2AuthnContext) state.getLocalVariable("urn:org:atricore:idbus:capabilities:josso:authnCtx"); SPInitiatedAuthnRequestType request = authnCtx != null ? authnCtx.getAuthnRequest() : null; if (request == null) { // Process unsolicited response validateUnsolicitedAuthnResposne(exchange, response); } else { validateSolicitedAuthnResponse(exchange, request, response); } OAuth2BPMediator bpMediator = (OAuth2BPMediator) channel.getIdentityMediator(); ResourceServer rServer = bpMediator.getResourceServer(); String rServerLocation = rServer.getResourceLocation(); CamelMediationMessage out = (CamelMediationMessage) exchange.getOut(); if (logger.isDebugEnabled()) logger.debug("Using Resource Server URL: [" + rServerLocation + " ]"); String accessToken = null; if (response.getSubject() == null) { // Authentication failed, return to the application // Create destination with back/to and OAUTH2 Restful binding EndpointDescriptor destination = new EndpointDescriptorImpl("OAuth2ResourceServer", "ErrorCode", OAuth2Binding.OAUTH2_RESTFUL.getValue(), rServerLocation, null); out.setMessage(new MediationMessageImpl(response.getID(), "authnFailed", "ErrorCode", null, destination, state)); } else { accessToken = resolveAccessToken(response); // Create destination with back/to and OAUTH2 Restful binding EndpointDescriptor destination = new EndpointDescriptorImpl("OAuth2ResourceServer", "AccessToken", OAuth2Binding.OAUTH2_RESTFUL.getValue(), rServerLocation, null); out.setMessage(new MediationMessageImpl(response.getID(), accessToken, "AccessToken", null, destination, state)); } // Clear authn-ctx once we're done state.removeLocalVariable("urn:org:atricore:idbus:capabilities:josso:authnCtx"); exchange.setOut(out); } protected void validateSolicitedAuthnResponse(CamelMediationExchange exchange, SPInitiatedAuthnRequestType request, SPAuthnResponseType response) throws OAuth2Exception { if (response == null) { throw new OAuth2Exception("No response found!"); } // TODO : Validate in-reply-to and other attributes: target acs, etc. if (response.getInReplayTo() == null || !request.getID().equals(response.getInReplayTo())) { throw new OAuth2Exception("Response is not a reply to " + request.getID() + " ["+(response.getInReplayTo() == null ? "<null>" : response.getInReplayTo())+"]"); } validateAuthnResponse(exchange, response); } protected void validateUnsolicitedAuthnResposne(CamelMediationExchange exchange, SPAuthnResponseType response) throws OAuth2Exception { //validateAuthnResponse(exchange, response); if (response == null) { throw new OAuth2Exception("No response found!"); } } protected void validateAuthnResponse(CamelMediationExchange exchange, SPAuthnResponseType response) throws OAuth2Exception { /* // Make sure that we have an OAUTH2 TOKEN if (resolveAccessToken(response) == null) { throw new OAuth2Exception("No token of type " + WSTConstants.WST_OAUTH2_TOKEN_TYPE + " received in subject attributes set"); } */ } protected String resolveAccessToken(SPAuthnResponseType response) { SubjectType subject = response.getSubject(); for (AbstractPrincipalType p : subject.getAbstractPrincipal()) { if (p instanceof SubjectAttributeType) { SubjectAttributeType attr = (SubjectAttributeType) p; if (attr.getName().equals(WSTConstants.WST_OAUTH2_TOKEN_TYPE)) { return attr.getValue(); } } } return null; } }