package org.atricore.idbus.capabilities.sso.main.binding; import org.apache.camel.Exchange; import org.apache.camel.Message; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.atricore.idbus.capabilities.sso.support.binding.SSOBinding; import org.atricore.idbus.common.sso._1_0.protocol.PreAuthenticatedTokenRequestType; import org.atricore.idbus.common.sso._1_0.protocol.PreAuthenticatedTokenResponseType; import org.atricore.idbus.kernel.main.federation.metadata.EndpointDescriptor; import org.atricore.idbus.kernel.main.mediation.Channel; import org.atricore.idbus.kernel.main.mediation.MediationMessage; import org.atricore.idbus.kernel.main.mediation.MediationMessageImpl; import org.atricore.idbus.kernel.main.mediation.MediationState; import org.atricore.idbus.kernel.main.mediation.camel.component.binding.AbstractMediationHttpBinding; import org.atricore.idbus.kernel.main.mediation.camel.component.binding.CamelMediationMessage; import java.util.Map; /** * Created by sgonzalez on 10/27/14. */ public class SsoPreAuthnTokenSvcBinding extends AbstractMediationHttpBinding { private static final Log logger = LogFactory.getLog(SsoPreAuthnTokenSvcBinding.class); public SsoPreAuthnTokenSvcBinding(Channel channel) { super(SSOBinding.SSO_PREAUTHN.getValue(), channel); } public MediationMessage createMessage(CamelMediationMessage message) { // The nested exchange contains HTTP information Exchange exchange = message.getExchange().getExchange(); logger.debug("Create Message Body from exchange " + exchange.getClass().getName()); Message httpMsg = exchange.getIn(); if (httpMsg.getHeader("http.requestMethod") == null) { if (logger.isDebugEnabled()) { Map<String, Object> h = httpMsg.getHeaders(); for (String key : h.keySet()) { logger.debug("CAMEL Header:" + key + ":"+ h.get(key)); } } throw new IllegalArgumentException("Unknown message, no valid HTTP Method header found!"); } // HTTP Request Parameters from HTTP Request body MediationState state = createMediationState(exchange); String relayState = state.getTransientVariable("relay_state"); String securityToken = state.getTransientVariable("atricore_security_token"); String id = state.getTransientVariable("response_id"); String scope = state.getTransientVariable("scope"); String authnCtx = state.getTransientVariable("authn_ctx"); String reply = state.getTransientVariable("reply"); Object content = null; if (scope != null && scope.equals("preauth-token")) { PreAuthenticatedTokenResponseType response = new PreAuthenticatedTokenResponseType(); response.setID(id); response.setSecurityToken(securityToken); response.setAuthnCtxClass(authnCtx); response.setInReplayTo(reply); content = response; } else { throw new IllegalArgumentException("scope not found or invalid : " + scope); } return new MediationMessageImpl(message.getMessageId(), content, null, relayState, null, state); } public void copyMessageToExchange(CamelMediationMessage msgOut, Exchange exchange) { // Content is OPTIONAL MediationMessage out = msgOut.getMessage(); EndpointDescriptor ed = out.getDestination(); // ------------------------------------------------------------ // Validate received message // ------------------------------------------------------------ assert ed != null : "Mediation Response MUST Provide a destination"; if (out.getContent() == null) throw new IllegalStateException("Content not found for IDBUS HTTP PreAuthnTokenSvc bidning, found: " + out); // ------------------------------------------------------------ // Create HTML Form for response body // ------------------------------------------------------------ if (logger.isDebugEnabled()) logger.debug("Creating HTML Redirect to " + ed.getLocation()); StringBuilder ssoQryString = new StringBuilder(); if (out.getContent() instanceof PreAuthenticatedTokenRequestType) { // Marshall pre-authn token request to query string PreAuthenticatedTokenRequestType req = (PreAuthenticatedTokenRequestType) out.getContent(); ssoQryString.append("?request_id=").append(req.getID()); if (out.getRelayState() != null) { ssoQryString.append("&relay_state=").append(out.getRelayState()); } if (req.getIssuer() != null) { ssoQryString.append("&issuer=").append(req.getIssuer()); } if (req.getAuthnCtxClass() != null) { ssoQryString.append("&atuhn_ctx=").append(req.getAuthnCtxClass()); } if (req.getTarget() != null) { ssoQryString.append("&target=").append(req.getTarget()); } } else { throw new IllegalStateException("Unsupported content type : " + out.getContent().getClass().getSimpleName()); } Message httpOut = exchange.getOut(); Message httpIn = exchange.getIn(); String ssoRedirLocation = this.buildHttpTargetLocation(httpIn, ed) + ssoQryString; if (logger.isDebugEnabled()) logger.debug("Redirecting to " + ssoRedirLocation); try { // ------------------------------------------------------------ // Prepare HTTP Resposne // ------------------------------------------------------------ copyBackState(out.getState(), exchange); httpOut.getHeaders().put("Cache-Control", "no-cache, no-store"); httpOut.getHeaders().put("Pragma", "no-cache"); httpOut.getHeaders().put("http.responseCode", 302); httpOut.getHeaders().put("Content-Type", "text/html"); httpOut.getHeaders().put("Location", ssoRedirLocation); handleCrossOriginResourceSharing(exchange); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } }