/* * JBoss, Home of Professional Open Source * * Copyright 2013 Red Hat, Inc. and/or its affiliates. * * Licensed 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.picketlink.identity.federation.web.process; import org.picketlink.common.exceptions.ConfigurationException; import org.picketlink.common.exceptions.ParsingException; import org.picketlink.common.exceptions.ProcessingException; import org.picketlink.common.util.DocumentUtil; import org.picketlink.config.federation.PicketLinkType; import org.picketlink.identity.federation.api.saml.v2.request.SAML2Request; import org.picketlink.identity.federation.core.saml.v2.common.SAMLDocumentHolder; import org.picketlink.identity.federation.core.saml.v2.holders.DestinationInfoHolder; import org.picketlink.identity.federation.core.saml.v2.impl.DefaultSAML2HandlerResponse; import org.picketlink.identity.federation.core.saml.v2.interfaces.SAML2Handler; import org.picketlink.identity.federation.core.saml.v2.interfaces.SAML2HandlerRequest; import org.picketlink.identity.federation.core.saml.v2.interfaces.SAML2HandlerResponse; import org.picketlink.identity.federation.saml.v2.SAML2Object; import org.picketlink.identity.federation.saml.v2.metadata.IDPSSODescriptorType; import org.picketlink.identity.federation.web.core.HTTPContext; import org.picketlink.identity.federation.web.util.HTTPRedirectUtil; import org.picketlink.identity.federation.web.util.PostBindingUtil; import org.picketlink.identity.federation.web.util.RedirectBindingUtil; import org.picketlink.identity.federation.web.util.RedirectBindingUtil.RedirectBindingUtilDestHolder; import org.w3c.dom.Document; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.util.Set; import java.util.concurrent.locks.Lock; /** * Utility Class to handle processing of an SAML Request Message * * @author Anil.Saldhana@redhat.com * @since Oct 27, 2009 */ public class ServiceProviderSAMLRequestProcessor extends ServiceProviderBaseProcessor { /** * Construct * * @param postBinding Whether it is the Post Binding * @param serviceURL Service URL of the SP */ public ServiceProviderSAMLRequestProcessor(boolean postBinding, String serviceURL, PicketLinkType configuration) { super(postBinding, serviceURL, configuration); } public ServiceProviderSAMLRequestProcessor(boolean postBinding, String serviceURL, PicketLinkType configuration, IDPSSODescriptorType idpMetadata) { super(postBinding, serviceURL, configuration, idpMetadata); } /** * Process the message * * @param samlRequest * @param httpContext * @param handlers * @param chainLock A Lock on the chain of handlers that needs to be used for locking * * @return * * @throws ProcessingException * @throws IOException * @throws ParsingException * @throws ConfigurationException */ public boolean process(String samlRequest, HTTPContext httpContext, Set<SAML2Handler> handlers, Lock chainLock) throws ProcessingException, IOException, ParsingException, ConfigurationException { SAML2Request saml2Request = new SAML2Request(); SAML2HandlerResponse saml2HandlerResponse = null; SAML2Object samlObject = null; SAMLDocumentHolder documentHolder = null; if (this.postBinding) { // we got a logout request from IDP InputStream is = PostBindingUtil.base64DecodeAsStream(samlRequest); samlObject = saml2Request.getSAML2ObjectFromStream(is); } else { InputStream is = RedirectBindingUtil.base64DeflateDecode(samlRequest); samlObject = saml2Request.getSAML2ObjectFromStream(is); } documentHolder = saml2Request.getSamlDocumentHolder(); // Create the request/response SAML2HandlerRequest saml2HandlerRequest = getSAML2HandlerRequest(documentHolder, httpContext); saml2HandlerResponse = new DefaultSAML2HandlerResponse(); saml2HandlerResponse.setPostBindingForResponse(postBinding); SAMLHandlerChainProcessor chainProcessor = new SAMLHandlerChainProcessor(handlers, this.configuration); // Set some request options setRequestOptions(saml2HandlerRequest); chainProcessor.callHandlerChain(samlObject, saml2HandlerRequest, saml2HandlerResponse, httpContext, chainLock); Document samlResponseDocument = saml2HandlerResponse.getResultingDocument(); String relayState = saml2HandlerResponse.getRelayState(); String destination = saml2HandlerResponse.getDestination(); boolean willSendRequest = saml2HandlerResponse.getSendRequest(); if (destination != null && samlResponseDocument != null) { if (postBinding) { sendRequestToIDP(destination, samlResponseDocument, relayState, httpContext.getResponse(), willSendRequest); } else { String destinationQuery = saml2HandlerResponse.getDestinationQueryStringWithSignature(); // This is the case with signatures disabled if (destinationQuery == null) { boolean areWeSendingRequest = saml2HandlerResponse.getSendRequest(); String samlMsg = DocumentUtil.getDocumentAsString(samlResponseDocument); String base64Request = RedirectBindingUtil.deflateBase64URLEncode(samlMsg.getBytes("UTF-8")); destinationQuery = RedirectBindingUtil.getDestinationQueryString(base64Request, relayState, areWeSendingRequest); } RedirectBindingUtilDestHolder holder = new RedirectBindingUtilDestHolder(); holder.setDestination(destination).setDestinationQueryString(destinationQuery); String destinationURL = RedirectBindingUtil.getDestinationURL(holder); HTTPRedirectUtil.sendRedirectForRequestor(destinationURL, httpContext.getResponse()); } return true; } return false; } /** * Send the request to the IDP * * @param destination idp url * @param samlDocument request or response document * @param relayState * @param response * @param willSendRequest are we sending Request or Response to IDP * * @throws ProcessingException * @throws ConfigurationException * @throws IOException */ protected void sendRequestToIDP(String destination, Document samlDocument, String relayState, HttpServletResponse response, boolean willSendRequest) throws ProcessingException, ConfigurationException, IOException { String samlMessage = DocumentUtil.getDocumentAsString(samlDocument); samlMessage = PostBindingUtil.base64Encode(samlMessage); PostBindingUtil.sendPost(new DestinationInfoHolder(destination, samlMessage, relayState), response, willSendRequest); } }