Package org.picketlink.identity.federation.bindings.tomcat.idp

Source Code of org.picketlink.identity.federation.bindings.tomcat.idp.AbstractIDPValve

/*
* JBoss, Home of Professional Open Source.
* Copyright 2012, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.picketlink.identity.federation.bindings.tomcat.idp;

import org.apache.catalina.*;
import org.apache.catalina.authenticator.SSLAuthenticator;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.deploy.LoginConfig;
import org.apache.catalina.realm.GenericPrincipal;
import org.apache.catalina.valves.ValveBase;
import org.apache.coyote.ActionCode;
import org.jboss.security.audit.AuditLevel;
import org.picketlink.identity.federation.PicketLinkLogger;
import org.picketlink.identity.federation.PicketLinkLoggerFactory;
import org.picketlink.identity.federation.bindings.tomcat.TomcatRoleGenerator;
import org.picketlink.identity.federation.core.audit.PicketLinkAuditEvent;
import org.picketlink.identity.federation.core.audit.PicketLinkAuditEventType;
import org.picketlink.identity.federation.core.audit.PicketLinkAuditHelper;
import org.picketlink.identity.federation.core.config.AuthPropertyType;
import org.picketlink.identity.federation.core.config.IDPType;
import org.picketlink.identity.federation.core.config.KeyProviderType;
import org.picketlink.identity.federation.core.config.PicketLinkType;
import org.picketlink.identity.federation.core.exceptions.ConfigurationException;
import org.picketlink.identity.federation.core.exceptions.ParsingException;
import org.picketlink.identity.federation.core.exceptions.ProcessingException;
import org.picketlink.identity.federation.core.handler.config.Handlers;
import org.picketlink.identity.federation.core.impl.DelegatedAttributeManager;
import org.picketlink.identity.federation.core.interfaces.AttributeManager;
import org.picketlink.identity.federation.core.interfaces.ProtocolContext;
import org.picketlink.identity.federation.core.interfaces.RoleGenerator;
import org.picketlink.identity.federation.core.interfaces.TrustKeyManager;
import org.picketlink.identity.federation.core.saml.v1.SAML11Constants;
import org.picketlink.identity.federation.core.saml.v1.SAML11ProtocolContext;
import org.picketlink.identity.federation.core.saml.v1.writers.SAML11ResponseWriter;
import org.picketlink.identity.federation.core.saml.v2.common.IDGenerator;
import org.picketlink.identity.federation.core.saml.v2.common.SAMLDocumentHolder;
import org.picketlink.identity.federation.core.saml.v2.constants.JBossSAMLURIConstants;
import org.picketlink.identity.federation.core.saml.v2.exceptions.IssuerNotTrustedException;
import org.picketlink.identity.federation.core.saml.v2.factories.SAML2HandlerChainFactory;
import org.picketlink.identity.federation.core.saml.v2.holders.IssuerInfoHolder;
import org.picketlink.identity.federation.core.saml.v2.impl.DefaultSAML2HandlerChainConfig;
import org.picketlink.identity.federation.core.saml.v2.impl.DefaultSAML2HandlerRequest;
import org.picketlink.identity.federation.core.saml.v2.impl.DefaultSAML2HandlerResponse;
import org.picketlink.identity.federation.core.saml.v2.interfaces.*;
import org.picketlink.identity.federation.core.saml.v2.interfaces.SAML2Handler.HANDLER_TYPE;
import org.picketlink.identity.federation.core.saml.v2.util.AssertionUtil;
import org.picketlink.identity.federation.core.saml.v2.util.DocumentUtil;
import org.picketlink.identity.federation.core.saml.v2.util.HandlerUtil;
import org.picketlink.identity.federation.core.saml.v2.util.XMLTimeUtil;
import org.picketlink.identity.federation.core.sts.PicketLinkCoreSTS;
import org.picketlink.identity.federation.core.util.*;
import org.picketlink.identity.federation.core.wstrust.PicketLinkSTSConfiguration;
import org.picketlink.identity.federation.saml.v1.assertion.*;
import org.picketlink.identity.federation.saml.v1.assertion.SAML11SubjectType.SAML11SubjectTypeChoice;
import org.picketlink.identity.federation.saml.v1.protocol.SAML11ResponseType;
import org.picketlink.identity.federation.saml.v1.protocol.SAML11StatusType;
import org.picketlink.identity.federation.saml.v2.SAML2Object;
import org.picketlink.identity.federation.saml.v2.metadata.EntityDescriptorType;
import org.picketlink.identity.federation.saml.v2.metadata.SPSSODescriptorType;
import org.picketlink.identity.federation.saml.v2.protocol.AuthnRequestType;
import org.picketlink.identity.federation.saml.v2.protocol.RequestAbstractType;
import org.picketlink.identity.federation.saml.v2.protocol.StatusResponseType;
import org.picketlink.identity.federation.web.config.AbstractSAMLConfigurationProvider;
import org.picketlink.identity.federation.web.constants.GeneralConstants;
import org.picketlink.identity.federation.web.core.HTTPContext;
import org.picketlink.identity.federation.web.core.IdentityParticipantStack;
import org.picketlink.identity.federation.web.core.IdentityServer;
import org.picketlink.identity.federation.web.util.ConfigurationUtil;
import org.picketlink.identity.federation.web.util.IDPWebRequestUtil;
import org.picketlink.identity.federation.web.util.IDPWebRequestUtil.WebRequestUtilHolder;
import org.picketlink.identity.federation.web.util.RedirectBindingUtil;
import org.picketlink.identity.federation.web.util.SAMLConfigurationProvider;
import org.w3c.dom.Document;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.Principal;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import static org.picketlink.identity.federation.core.util.StringUtil.isNotNull;
import static org.picketlink.identity.federation.core.util.StringUtil.isNullOrEmpty;

/**
* Base Class for the IDPWebBrowserSSOValve
*
* @author anil saldhana
*/
public abstract class AbstractIDPValve extends ValveBase {

    private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();

    protected boolean enableAudit = false;

    protected PicketLinkAuditHelper auditHelper = null;

    protected IDPType idpConfiguration = null;

    protected PicketLinkType picketLinkConfiguration = null;

    private RoleGenerator roleGenerator = new TomcatRoleGenerator();

    private TrustKeyManager keyManager;

    private transient DelegatedAttributeManager attribManager = new DelegatedAttributeManager();

    private final List<String> attributeKeys = new ArrayList<String>();

    private transient SAML2HandlerChain chain = null;

    /**
     * The user can inject a fully qualified name of a {@link SAMLConfigurationProvider}
     */
    protected SAMLConfigurationProvider configProvider = null;

    /**
     * A Lock for Handler operations in the chain
     */
    private final Lock chainLock = new ReentrantLock();

    private Map<String, SPSSODescriptorType> spSSOMetadataMap = new HashMap<String, SPSSODescriptorType>();
    private SSLAuthenticator sslAuthenticator;

    private Boolean passUserPrincipalToAttributeManager = false;

    /**
     * Character encoding to use when reading the request parameters
     */
    protected String characterEncoding = null;

    /**
     * Return the character encoding to use when reading the request parameters
     */
    public String getCharacterEncoding() {
        return characterEncoding;
    }

    /**
     * Set the character encoding to use when reading the request parameters
     */
    public void setCharacterEncoding(String encoding) {
        characterEncoding = encoding;
    }

    // Set a list of attributes we are interested in separated by comma
    public void setAttributeList(String attribList) {
        if (StringUtil.isNotNull(attribList)) {
            this.attributeKeys.clear();
            this.attributeKeys.addAll(StringUtil.tokenize(attribList));
        }
    }

    /**
     * Set the {@link SAMLConfigurationProvider} fqn
     *
     * @param cp fqn of a {@link SAMLConfigurationProvider}
     */
    public void setConfigProvider(String cp) {
        if (cp == null)
            throw logger.nullArgumentError("configProvider");
        Class<?> clazz = SecurityActions.loadClass(getClass(), cp);
        if (clazz == null)
            throw new RuntimeException(logger.classNotLoadedError(cp));
        try {
            configProvider = (SAMLConfigurationProvider) clazz.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(logger.couldNotCreateInstance(cp, e));
        }
    }

    public void setConfigProvider(SAMLConfigurationProvider configurationProvider) {
        this.configProvider = configurationProvider;
    }

    @Deprecated
    public void setRoleGenerator(String rgName) {
        logger.warn("Option 'roleGenerator' is deprecated and should not be used. This configuration is now set in picketlink.xml.");
    }

    @Deprecated
    public void setSamlHandlerChainClass(String samlHandlerChainClass) {
        logger.warn("Option 'samlHandlerChainClass' is deprecated and should not be used. This configuration is now set in picketlink.xml.");
    }

    @Deprecated
    public void setIdentityParticipantStack(String fqn) {
        logger.warn("Option 'identityParticipantStack' is deprecated and should not be used. This configuration is now set in picketlink.xml.");
    }

    @Deprecated
    public void setStrictPostBinding(Boolean strictPostBinding) {
        logger.warn("Option 'strictPostBinding' is deprecated and should not be used. This configuration is now set in picketlink.xml.");
    }

    @Deprecated
    public Boolean getIgnoreIncomingSignatures() {
        logger.warn("Option 'ignoreIncomingSignatures' is deprecated and should not be used. Signatures are verified if "
                + "SAML2SignatureValidationHandler is available.");
        return false;
    }

    @Deprecated
    public void setIgnoreIncomingSignatures(Boolean ignoreIncomingSignature) {
        logger.warn("Option 'ignoreIncomingSignatures' is deprecated and not used. Signatures are verified if "
                + "SAML2SignatureValidationHandler is available.");
    }

    /**
     * PLFED-248 Allows to validate the token's signature against the keystore using the token's issuer.
     */
    @Deprecated
    public void setValidatingAliasToTokenIssuer(Boolean validatingAliasToTokenIssuer) {
        logger.warn("Option 'validatingAliasToTokenIssuer' is deprecated and not used. The IDP will always use the issuer host to validate signatures.");
    }

    /**
     * IDP should not do any attributes such as generation of roles etc
     *
     * @param ignoreAttributes
     */
    public void setIgnoreAttributesGeneration(Boolean ignoreAttributes) {
        if (ignoreAttributes == Boolean.TRUE)
            this.attribManager = null;
    }

    @Deprecated
    public Boolean getSignOutgoingMessages() {
        logger.warn("Option signOutgoingMessages is used for signing of error messages. Normal SAML messages are "
                + "signed by SAML2SignatureGenerationHandler.");
        return true;
    }

    @Deprecated
    public void setSignOutgoingMessages(Boolean signOutgoingMessages) {
        logger.warn("Option signOutgoingMessages is used for signing of error messages. Normal SAML messages are "
                + "signed by SAML2SignatureGenerationHandler.");
    }

    /**
     * IDP should get the user principal from Request.getUserPrincipal() and send that to the attribute manager
     *
     * @param passUserPrincipalToAttributeManager
     */
    public void setPassUserPrincipalToAttributeManager(Boolean passUserPrincipalToAttributeManager) {
        this.passUserPrincipalToAttributeManager = passUserPrincipalToAttributeManager;
    }

    /**
     * <p>
     * Returns the configurations used.
     * </p>
     *
     * @return
     */
    public PicketLinkType getConfiguration() {
        return this.picketLinkConfiguration;
    }

    /**
     * Return the {@link TrustKeyManager}
     *
     * @return
     */
    public TrustKeyManager getKeyManager() {
        return this.keyManager;
    }

    @Override
    public void invoke(Request request, Response response) throws IOException, ServletException {
        String characterEncoding = getCharacterEncoding();
        if (characterEncoding != null) {
            request.setCharacterEncoding(characterEncoding);
        }

        // Look for unauthorized status
        if (isUnauthorized(response)) {
            handleUnauthorizedResponse(request, response);
            return;
        }

        // first, we populate all required parameters sent into session for later retrieval. If they exists.
        populateSessionWithSAMLParameters(request);

        // get an authenticated user or tries to authenticate if this is a authentication request
        Principal userPrincipal = getUserPrincipal(request, response);

        // we only handle SAML messages for authenticated users.
        if (userPrincipal != null) {
            handleSAMLMessage(request, response);
        }
    }

    /**
     * <p>
     * Handles SAML messages.
     * </p>
     *
     * @param request
     * @param response
     * @throws IOException
     * @throws ServletException
     */
    private void handleSAMLMessage(Request request, Response response) throws IOException, ServletException {
        if (hasSAML11Target(request)) {
            // We have SAML 1.1 IDP first scenario. Now we need to create a SAMLResponse and send back
            // to SP as per target
            handleSAML11(request, response);
        } else {
            Session session = request.getSessionInternal();

            String samlRequestMessage = (String) session.getNote(GeneralConstants.SAML_REQUEST_KEY);
            String samlResponseMessage = (String) session.getNote(GeneralConstants.SAML_RESPONSE_KEY);

            /**
             * Since the container has finished the authentication, we can retrieve the original saml message as well as any
             * relay state from the SP
             */
            String relayState = (String) session.getNote(GeneralConstants.RELAY_STATE);
            String signature = (String) session.getNote(GeneralConstants.SAML_SIGNATURE_REQUEST_KEY);
            String sigAlg = (String) session.getNote(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY);

            if (logger.isTraceEnabled()) {
                StringBuilder builder = new StringBuilder();
                builder.append("Retrieved saml messages and relay state from session");
                builder.append("saml Request message=").append(samlRequestMessage);
                builder.append("::").append("SAMLResponseMessage=");
                builder.append(samlResponseMessage).append(":").append("relay state=").append(relayState);

                builder.append("Signature=").append(signature).append("::sigAlg=").append(sigAlg);
                logger.trace(builder.toString());
            }

            if (isNotNull(samlRequestMessage)) {
                processSAMLRequestMessage(request, response);
            } else if (isNotNull(samlResponseMessage)) {
                processSAMLResponseMessage(request, response);
            } else if (request.getRequestURI().equals(request.getContextPath() + "/")) {
                // no SAML processing and the request is asking for /.
                forwardHosted(request, response);
            }
        }
    }

    /**
     * <p>
     * Checks if the given {@link Request} containes a SAML11 Target parameter. Usually this indicates that the given request is
     * a SAML11 request.
     * </p>
     *
     * @param request
     * @return
     */
    private boolean hasSAML11Target(Request request) {
        return isNotNull(request.getParameter(SAML11Constants.TARGET));
    }

    private void forwardHosted(Request request, Response response) throws ServletException, IOException {
        logger.trace("SAML 1.1::Proceeding to IDP index page");
        RequestDispatcher dispatch = getContext().getServletContext()
                .getRequestDispatcher(this.idpConfiguration.getHostedURI());

        recycle(response);

        try {
            includeResource(request, response, dispatch);
        } catch (ClassCastException cce) {
            // JBAS5.1 and 6 quirkiness
            includeResource(request.getRequest(), response, dispatch);
        }
    }

    /**
     * <p>
     * Before forwarding we need to know the content length of the target resource in order to configure the response properly.
     * This is necessary because the valve already have written to the response, and we want to override with the target
     * resource data.
     * </p>
     *
     * @param request
     * @param response
     * @param dispatch
     * @throws ServletException
     * @throws IOException
     */
    private void includeResource(ServletRequest request, Response response, RequestDispatcher dispatch)
            throws ServletException, IOException {
        dispatch.include(request, response);

        // we need to re-configure the content length because Tomcat will truncate the output with the size of the welcome page
        // (eg.: index.html).
        response.getCoyoteResponse().setContentLength(response.getContentCount());
    }

    /**
     * <p>
     * SAML parameters are also populated into session if they are present in the request. This allows the IDP to retrieve them
     * later when handling a specific SAML request or response.
     * </p>
     *
     * @param request
     * @return
     * @throws IOException
     */
    private void populateSessionWithSAMLParameters(Request request) throws IOException {
        String samlRequestMessage = request.getParameter(GeneralConstants.SAML_REQUEST_KEY);
        String samlResponseMessage = request.getParameter(GeneralConstants.SAML_RESPONSE_KEY);

        boolean containsSAMLRequestMessage = isNotNull(samlRequestMessage);
        boolean containsSAMLResponseMessage = isNotNull(samlResponseMessage);

        String signature = request.getParameter(GeneralConstants.SAML_SIGNATURE_REQUEST_KEY);
        String sigAlg = request.getParameter(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY);
        String relayState = request.getParameter(GeneralConstants.RELAY_STATE);

        Session session = request.getSessionInternal();

        if (containsSAMLRequestMessage || containsSAMLResponseMessage) {
            logger.trace("Storing the SAMLRequest/SAMLResponse and RelayState in session");
            if (isNotNull(samlRequestMessage))
                session.setNote(GeneralConstants.SAML_REQUEST_KEY, samlRequestMessage);
            if (isNotNull(samlResponseMessage))
                session.setNote(GeneralConstants.SAML_RESPONSE_KEY, samlResponseMessage);
            if (isNotNull(relayState))
                session.setNote(GeneralConstants.RELAY_STATE, relayState.trim());
            if (isNotNull(signature))
                session.setNote(GeneralConstants.SAML_SIGNATURE_REQUEST_KEY, signature.trim());
            if (isNotNull(sigAlg))
                session.setNote(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY, sigAlg.trim());
        }
    }

    /**
     * <p>
     * Handles an unauthorized response returned by a service provider.
     * </p>
     *
     * @param request
     * @param response
     * @throws IOException
     * @throws ServletException
     */
    private void handleUnauthorizedResponse(Request request, Response response) throws IOException, ServletException {
        IDPWebRequestUtil webRequestUtil = new IDPWebRequestUtil(request, idpConfiguration, keyManager);
        Document samlErrorResponse = null;
        String referer = request.getHeader("Referer");
        String relayState = request.getParameter(GeneralConstants.RELAY_STATE);

        try {
            samlErrorResponse = webRequestUtil.getErrorResponse(referer, JBossSAMLURIConstants.STATUS_AUTHNFAILED.get(),
                    getIdentityURL(), this.idpConfiguration.isSupportsSignature());

            WebRequestUtilHolder holder = webRequestUtil.getHolder();
            holder.setResponseDoc(samlErrorResponse).setDestination(referer).setRelayState(relayState)
                    .setAreWeSendingRequest(false).setPrivateKey(null).setSupportSignature(false).setServletResponse(response)
                    .setErrorResponse(true);
            holder.setPostBindingRequested(webRequestUtil.hasSAMLRequestInPostProfile());

            if (this.idpConfiguration.isSupportsSignature()) {
                holder.setSupportSignature(true).setPrivateKey(keyManager.getSigningKey());
            }

            holder.setStrictPostBinding(this.idpConfiguration.isStrictPostBinding());

            webRequestUtil.send(holder);
        } catch (GeneralSecurityException e) {
            throw new ServletException(e);
        }
    }

    private boolean isUnauthorized(Response response) {
        return response.getStatus() == HttpServletResponse.SC_FORBIDDEN;
    }

    /**
     * <p>
     * Returns the authenticated principal. If there is no principal associated with the {@link Request}, null is returned.
     * </p>
     *
     * @param request
     * @param response
     * @return
     * @throws IOException
     * @throws ServletException
     */
    private Principal getUserPrincipal(Request request, Response response) throws IOException, ServletException {
        Principal userPrincipal = request.getPrincipal();

        if (userPrincipal == null) {
            if (this.idpConfiguration.isSSLClientAuthentication()) {
                if (request.isSecure()) {
                    getSSLAuthenticator().invoke(request, response);

                    // we always reset/recycle the response to remove any data written to the response by the ssl
                    // authenticator
                    response.resetBuffer();
                    response.recycle();
                }
            }

            userPrincipal = request.getPrincipal();

            // we always fall back to the configured authentication method.
            if (userPrincipal == null) {
                getNext().invoke(request, response);
            }

            userPrincipal = request.getPrincipal();
        }

        return userPrincipal;
    }

    public Principal authenticateSSL(Request request, Response response) throws IOException {
        // Retrieve the certificate chain for this client
        if (containerLog.isDebugEnabled())
            containerLog.debug(" Looking up certificates");

        X509Certificate certs[] = (X509Certificate[]) request.getAttribute(Globals.CERTIFICATES_ATTR);

        if ((certs == null) || (certs.length < 1)) {
            try {
                request.getCoyoteRequest().action(ActionCode.ACTION_REQ_SSL_CERTIFICATE, null);
            } catch (IllegalStateException ise) {
                // Request body was too large for save buffer
                response.sendError(HttpServletResponse.SC_UNAUTHORIZED, sm.getString("authenticator.certificates"));
                return null;
            }
            certs = (X509Certificate[]) request.getAttribute(Globals.CERTIFICATES_ATTR);
        }

        if ((certs == null) || (certs.length < 1)) {
            if (containerLog.isDebugEnabled())
                containerLog.debug("  No certificates included with this request");
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, sm.getString("authenticator.certificates"));
            return null;
        }

        // Authenticate the specified certificate chain
        Principal principal = getContext().getRealm().authenticate(certs);

        if (principal == null) {
            if (containerLog.isDebugEnabled())
                containerLog.debug("  Realm.authenticate() returned false");
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, sm.getString("authenticator.unauthorized"));
            return null;
        }

        return principal;
    }

    protected void handleSAML11(Request request, Response response) throws ServletException, IOException {
        try {
            IDPWebRequestUtil webRequestUtil = new IDPWebRequestUtil(request, idpConfiguration, keyManager);

            Principal userPrincipal = request.getPrincipal();
            String contextPath = getContextPath();

            String target = request.getParameter(SAML11Constants.TARGET);

            Session session = request.getSessionInternal();
            SAML11AssertionType saml11Assertion = (SAML11AssertionType) session.getNote("SAML11");
            if (saml11Assertion == null) {
                SAML11ProtocolContext saml11Protocol = new SAML11ProtocolContext();
                saml11Protocol.setIssuerID(getIdentityURL());
                SAML11SubjectType subject = new SAML11SubjectType();
                SAML11SubjectTypeChoice subjectChoice = new SAML11SubjectTypeChoice(new SAML11NameIdentifierType(
                        userPrincipal.getName()));
                subject.setChoice(subjectChoice);
                saml11Protocol.setSubjectType(subject);

                PicketLinkCoreSTS.instance().issueToken(saml11Protocol);
                saml11Assertion = saml11Protocol.getIssuedAssertion();
                session.setNote("SAML11", saml11Assertion);

                if (AssertionUtil.hasExpired(saml11Assertion)) {
                    saml11Protocol.setIssuedAssertion(saml11Assertion);
                    PicketLinkCoreSTS.instance().renewToken(saml11Protocol);
                    saml11Assertion = saml11Protocol.getIssuedAssertion();
                    session.setNote("SAML11", saml11Assertion);
                }
            }
            GenericPrincipal genericPrincipal = (GenericPrincipal) userPrincipal;
            String[] roles = genericPrincipal.getRoles();
            SAML11AttributeStatementType attributeStatement = this.createAttributeStatement(Arrays.asList(roles));
            if (attributeStatement != null) {
                saml11Assertion.add(attributeStatement);
            }

            // Send it as SAMLResponse
            String id = IDGenerator.create("ID_");
            SAML11ResponseType saml11Response = new SAML11ResponseType(id, XMLTimeUtil.getIssueInstant());
            saml11Response.add(saml11Assertion);
            saml11Response.setStatus(SAML11StatusType.successType());

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            SAML11ResponseWriter writer = new SAML11ResponseWriter(StaxUtil.getXMLStreamWriter(baos));
            writer.write(saml11Response);

            Document samlResponse = DocumentUtil.getDocument(new ByteArrayInputStream(baos.toByteArray()));

            WebRequestUtilHolder holder = webRequestUtil.getHolder();
            holder.setResponseDoc(samlResponse).setDestination(target).setRelayState("").setAreWeSendingRequest(false)
                    .setPrivateKey(null).setSupportSignature(false).setServletResponse(response);

            if (enableAudit) {
                PicketLinkAuditEvent auditEvent = new PicketLinkAuditEvent(AuditLevel.INFO);
                auditEvent.setType(PicketLinkAuditEventType.RESPONSE_TO_SP);
                auditEvent.setDestination(target);
                auditEvent.setWhoIsAuditing(contextPath);
                auditHelper.audit(auditEvent);
            }

            response.getCoyoteResponse().recycle();

            webRequestUtil.send(holder);
        } catch (GeneralSecurityException e) {
            logger.samlIDPHandlingSAML11Error(e);
            throw new ServletException();
        }
    }

    protected void processSAMLRequestMessage(Request request, Response response) throws IOException {
        Principal userPrincipal = request.getPrincipal();
        Session session = request.getSessionInternal();
        SAMLDocumentHolder samlDocumentHolder = null;
        SAML2Object samlObject = null;

        Document samlResponse = null;
        boolean isErrorResponse = false;
        String destination = null;
        String destinationQueryStringWithSignature = null;

        Boolean requestedPostProfile = null;

        String samlRequestMessage = (String) session.getNote(GeneralConstants.SAML_REQUEST_KEY);

        String relayState = (String) session.getNote(GeneralConstants.RELAY_STATE);

        String contextPath = getContextPath();

        boolean willSendRequest = false;

        String referer = request.getHeader("Referer");

        cleanUpSessionNote(request);

        // Determine the transport mechanism
        boolean isSecure = request.isSecure();
        String loginType = determineLoginType(isSecure);

        IDPWebRequestUtil webRequestUtil = new IDPWebRequestUtil(request, idpConfiguration, keyManager);

        try {
            samlDocumentHolder = webRequestUtil.getSAMLDocumentHolder(samlRequestMessage);
            samlObject = samlDocumentHolder.getSamlObject();

            if (!(samlObject instanceof RequestAbstractType)) {
                throw logger.wrongTypeError(samlObject.getClass().getName());
            }

            // Get the SAML Request Message
            RequestAbstractType requestAbstractType = (RequestAbstractType) samlObject;
            String issuer = requestAbstractType.getIssuer().getValue();

            if (samlRequestMessage == null)
                throw logger.samlIDPValidationCheckFailed();

            IssuerInfoHolder idpIssuer = new IssuerInfoHolder(getIdentityURL());
            ProtocolContext protocolContext = new HTTPContext(request, response, getContext().getServletContext());
            // Create the request/response
            SAML2HandlerRequest saml2HandlerRequest = new DefaultSAML2HandlerRequest(protocolContext, idpIssuer.getIssuer(),
                    samlDocumentHolder, HANDLER_TYPE.IDP);
            saml2HandlerRequest.setRelayState(relayState);
            if (StringUtil.isNotNull(loginType)) {
                saml2HandlerRequest.addOption(GeneralConstants.LOGIN_TYPE, loginType);
            }

            String assertionID = (String) session.getSession().getAttribute(GeneralConstants.ASSERTION_ID);

            // Set the options on the handler request
            Map<String, Object> requestOptions = new HashMap<String, Object>();

            requestOptions.put(GeneralConstants.IGNORE_SIGNATURES, willIgnoreSignatureOfCurrentRequest(issuer));
            requestOptions.put(GeneralConstants.SP_SSO_METADATA_DESCRIPTOR, spSSOMetadataMap.get(issuer));
            requestOptions.put(GeneralConstants.ROLE_GENERATOR, roleGenerator);
            requestOptions.put(GeneralConstants.CONFIGURATION, this.idpConfiguration);
            requestOptions.put(GeneralConstants.SAML_IDP_STRICT_POST_BINDING, this.idpConfiguration.isStrictPostBinding());
            requestOptions.put(GeneralConstants.SUPPORTS_SIGNATURES, this.idpConfiguration.isSupportsSignature());

            if (assertionID != null)
                requestOptions.put(GeneralConstants.ASSERTION_ID, assertionID);

            if (this.keyManager != null) {
                PublicKey validatingKey = getIssuerPublicKey(request, issuer);
                requestOptions.put(GeneralConstants.SENDER_PUBLIC_KEY, validatingKey);
                requestOptions.put(GeneralConstants.DECRYPTING_KEY, keyManager.getSigningKey());
            }

            // if this is a SAML AuthnRequest load the roles using the generator.
            if (requestAbstractType instanceof AuthnRequestType) {
                List<String> roles = roleGenerator.generateRoles(userPrincipal);
                session.getSession().setAttribute(GeneralConstants.ROLES_ID, roles);

                Map<String, Object> attribs = this.attribManager.getAttributes(
                                     passUserPrincipalToAttributeManager == true
                                         ?  request.getUserPrincipal()
                                         : userPrincipal,
                                     attributeKeys);
                requestOptions.put(GeneralConstants.ATTRIBUTES, attribs);
            }

            if (auditHelper != null) {
                requestOptions.put(GeneralConstants.AUDIT_HELPER, auditHelper);
                requestOptions.put(GeneralConstants.CONTEXT_PATH, contextPath);
            }

            saml2HandlerRequest.setOptions(requestOptions);

            SAML2HandlerResponse saml2HandlerResponse = new DefaultSAML2HandlerResponse();

            Set<SAML2Handler> handlers = chain.handlers();

            logger.trace("Handlers are=" + handlers);

            // the trusted domains is done by a handler
            // webRequestUtil.isTrusted(issuer);

            if (handlers != null) {
                try {
                    chainLock.lock();
                    for (SAML2Handler handler : handlers) {
                        handler.handleRequestType(saml2HandlerRequest, saml2HandlerResponse);
                        willSendRequest = saml2HandlerResponse.getSendRequest();
                    }
                } finally {
                    chainLock.unlock();
                }
            }

            samlResponse = saml2HandlerResponse.getResultingDocument();
            relayState = saml2HandlerResponse.getRelayState();

            destination = saml2HandlerResponse.getDestination();

            requestedPostProfile = saml2HandlerResponse.isPostBindingForResponse();
            destinationQueryStringWithSignature = saml2HandlerResponse.getDestinationQueryStringWithSignature();
        } catch (Exception e) {
            String status = JBossSAMLURIConstants.STATUS_AUTHNFAILED.get();
            if (e instanceof IssuerNotTrustedException || e.getCause() instanceof IssuerNotTrustedException) {
                status = JBossSAMLURIConstants.STATUS_REQUEST_DENIED.get();
            }
            logger.samlIDPRequestProcessingError(e);
            samlResponse = webRequestUtil.getErrorResponse(referer, status, getIdentityURL(),
                    this.idpConfiguration.isSupportsSignature());
            isErrorResponse = true;
        } finally {
            try {
                // if the destination is null, probably because some error occur during authentication, use the AuthnRequest
                // AssertionConsumerServiceURL as the destination
                if (destination == null && samlObject instanceof AuthnRequestType) {
                    AuthnRequestType authRequest = (AuthnRequestType) samlObject;

                    destination = authRequest.getAssertionConsumerServiceURL().toASCIIString();
                }

                // if destination is still empty redirect the user to the identity url. If the user is already authenticated he
                // will be probably redirected to the idp hosted page.
                if (destination == null) {
                    response.sendRedirect(getIdentityURL());
                } else {
                    WebRequestUtilHolder holder = webRequestUtil.getHolder();
                    holder.setResponseDoc(samlResponse).setDestination(destination).setRelayState(relayState)
                            .setAreWeSendingRequest(willSendRequest).setPrivateKey(null).setSupportSignature(false)
                            .setErrorResponse(isErrorResponse).setServletResponse(response)
                            .setDestinationQueryStringWithSignature(destinationQueryStringWithSignature);

                    holder.setStrictPostBinding(this.idpConfiguration.isStrictPostBinding());

                    if (requestedPostProfile != null)
                        holder.setPostBindingRequested(requestedPostProfile);
                    else
                        holder.setPostBindingRequested(webRequestUtil.hasSAMLRequestInPostProfile());

                    if (this.idpConfiguration.isSupportsSignature()) {
                        holder.setPrivateKey(keyManager.getSigningKey()).setSupportSignature(true);
                    }

                    if (holder.isPostBinding())
                        recycle(response);

                    if (enableAudit) {
                        PicketLinkAuditEvent auditEvent = new PicketLinkAuditEvent(AuditLevel.INFO);
                        auditEvent.setType(PicketLinkAuditEventType.RESPONSE_TO_SP);
                        auditEvent.setDestination(destination);
                        auditEvent.setWhoIsAuditing(contextPath);
                        auditHelper.audit(auditEvent);
                    }

                    webRequestUtil.send(holder);
                }
            } catch (ParsingException e) {
                logger.samlAssertionPasingFailed(e);
            } catch (GeneralSecurityException e) {
                logger.trace("Security Exception:", e);
            } catch (Exception e) {
                System.out.println(e);
            }
        }
        return;
    }

    /**
     * Returns the PublicKey to be used for the token's signature verification. This key is related with the issuer of the SAML
     * message received by the IDP.
     *
     * @param request
     * @param issuer
     * @return
     * @throws ProcessingException
     * @throws ConfigurationException
     */
    private PublicKey getIssuerPublicKey(Request request, String issuer) throws ConfigurationException, ProcessingException {
        String issuerHost = null;
        PublicKey issuerPublicKey = null;

        try {
            issuerHost = new URL(issuer).getHost();
        } catch (MalformedURLException e) {
            logger.trace("Token issuer is not a valid URL: " + issuer, e);
            issuerHost = issuer;
        }

        logger.trace("Trying to find a PK for issuer: " + issuerHost);
        try {
            issuerPublicKey = CoreConfigUtil.getValidatingKey(keyManager, issuerHost);
        } catch (IllegalStateException ise) {
            logger.trace("Token issuer is not found for: " + issuer, ise);
        }

        if (issuerPublicKey == null) {
            issuerHost = request.getRemoteAddr();

            logger.trace("Trying to find a PK for issuer " + issuerHost);
            issuerPublicKey = CoreConfigUtil.getValidatingKey(keyManager, issuerHost);
        }

        logger.trace("Using Validating Alias=" + issuerHost + " to check signatures.");

        return issuerPublicKey;
    }

    protected void processSAMLResponseMessage(Request request, Response response) throws ServletException, IOException {
        Session session = request.getSessionInternal();
        SAMLDocumentHolder samlDocumentHolder = null;
        SAML2Object samlObject = null;

        Document samlResponse = null;
        boolean isErrorResponse = false;
        String destination = null;
        String destinationQueryStringWithSignature = null;

        String contextPath = getContextPath();

        boolean requestedPostProfile = false;

        // Get the SAML Response Message
        String samlResponseMessage = (String) session.getNote(GeneralConstants.SAML_RESPONSE_KEY);
        String relayState = (String) session.getNote(GeneralConstants.RELAY_STATE);

        boolean willSendRequest = false;

        String referer = request.getHeader("Referer");

        cleanUpSessionNote(request);

        IDPWebRequestUtil webRequestUtil = new IDPWebRequestUtil(request, idpConfiguration, keyManager);

        try {
            samlDocumentHolder = webRequestUtil.getSAMLDocumentHolder(samlResponseMessage);
            samlObject = samlDocumentHolder.getSamlObject();

            if (!(samlObject instanceof StatusResponseType)) {
                throw logger.wrongTypeError(samlObject.getClass().getName());
            }

            StatusResponseType statusResponseType = (StatusResponseType) samlObject;
            String issuer = statusResponseType.getIssuer().getValue();

            boolean isValid = samlResponseMessage != null;

            if (!isValid)
                throw logger.samlIDPValidationCheckFailed();

            IssuerInfoHolder idpIssuer = new IssuerInfoHolder(getIdentityURL());
            ProtocolContext protocolContext = new HTTPContext(request, response, getContext().getServletContext());
            // Create the request/response
            SAML2HandlerRequest saml2HandlerRequest = new DefaultSAML2HandlerRequest(protocolContext, idpIssuer.getIssuer(),
                    samlDocumentHolder, HANDLER_TYPE.IDP);
            Map<String, Object> options = new HashMap<String, Object>();

            if (this.idpConfiguration.isSupportsSignature() || this.idpConfiguration.isEncrypt()) {
                PublicKey publicKey = getIssuerPublicKey(request, issuer);
                options.put(GeneralConstants.SENDER_PUBLIC_KEY, publicKey);
            }

            options.put(GeneralConstants.SAML_IDP_STRICT_POST_BINDING, this.idpConfiguration.isStrictPostBinding());
            options.put(GeneralConstants.SUPPORTS_SIGNATURES, this.idpConfiguration.isSupportsSignature());
            if (auditHelper != null) {
                options.put(GeneralConstants.AUDIT_HELPER, auditHelper);
                options.put(GeneralConstants.CONTEXT_PATH, contextPath);
            }

            saml2HandlerRequest.setOptions(options);
            saml2HandlerRequest.setRelayState(relayState);

            SAML2HandlerResponse saml2HandlerResponse = new DefaultSAML2HandlerResponse();

            Set<SAML2Handler> handlers = chain.handlers();

            // the trusted domains is done by a handler
            // webRequestUtil.isTrusted(issuer);

            if (handlers != null) {
                try {
                    chainLock.lock();
                    for (SAML2Handler handler : handlers) {
                        handler.reset();
                        handler.handleStatusResponseType(saml2HandlerRequest, saml2HandlerResponse);
                        willSendRequest = saml2HandlerResponse.getSendRequest();
                    }
                } finally {
                    chainLock.unlock();
                }
            }

            samlResponse = saml2HandlerResponse.getResultingDocument();
            relayState = saml2HandlerResponse.getRelayState();

            destination = saml2HandlerResponse.getDestination();
            requestedPostProfile = saml2HandlerResponse.isPostBindingForResponse();
            destinationQueryStringWithSignature = saml2HandlerResponse.getDestinationQueryStringWithSignature();
        } catch (Exception e) {
            String status = JBossSAMLURIConstants.STATUS_AUTHNFAILED.get();
            if (e instanceof IssuerNotTrustedException) {
                status = JBossSAMLURIConstants.STATUS_REQUEST_DENIED.get();
            }
            logger.samlIDPRequestProcessingError(e);
            samlResponse = webRequestUtil.getErrorResponse(referer, status, getIdentityURL(),
                    this.idpConfiguration.isSupportsSignature());
            isErrorResponse = true;
        } finally {
            try {
                WebRequestUtilHolder holder = webRequestUtil.getHolder();
                if (destination == null)
                    throw new ServletException(logger.nullValueError("Destination"));
                holder.setResponseDoc(samlResponse).setDestination(destination).setRelayState(relayState)
                        .setAreWeSendingRequest(willSendRequest).setPrivateKey(null).setSupportSignature(false)
                        .setErrorResponse(isErrorResponse).setServletResponse(response)
                        .setPostBindingRequested(requestedPostProfile)
                        .setDestinationQueryStringWithSignature(destinationQueryStringWithSignature);

                /*
                 * if (requestedPostProfile) holder.setPostBindingRequested(requestedPostProfile); else
                 * holder.setPostBindingRequested(postProfile);
                 */

                if (this.idpConfiguration.isSupportsSignature()) {
                    holder.setPrivateKey(keyManager.getSigningKey()).setSupportSignature(true);
                }

                holder.setStrictPostBinding(this.idpConfiguration.isStrictPostBinding());

                if (holder.isPostBinding())
                    recycle(response);

                if (enableAudit) {
                    PicketLinkAuditEvent auditEvent = new PicketLinkAuditEvent(AuditLevel.INFO);
                    auditEvent.setType(PicketLinkAuditEventType.RESPONSE_TO_SP);
                    auditEvent.setWhoIsAuditing(contextPath);
                    auditEvent.setDestination(destination);
                    auditHelper.audit(auditEvent);
                }
                webRequestUtil.send(holder);
            } catch (ParsingException e) {
                logger.samlAssertionPasingFailed(e);
            } catch (GeneralSecurityException e) {
                logger.trace("Security Exception:", e);
            }
        }
        return;
    }

    protected void cleanUpSessionNote(Request request) {
        Session session = request.getSessionInternal();
        /**
         * Since the container has finished the authentication, we can retrieve the original saml message as well as any relay
         * state from the SP
         */
        String samlRequestMessage = (String) session.getNote(GeneralConstants.SAML_REQUEST_KEY);

        String samlResponseMessage = (String) session.getNote(GeneralConstants.SAML_RESPONSE_KEY);
        String relayState = (String) session.getNote(GeneralConstants.RELAY_STATE);
        String signature = (String) session.getNote(GeneralConstants.SAML_SIGNATURE_REQUEST_KEY);
        String sigAlg = (String) session.getNote(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY);

        if (logger.isTraceEnabled()) {
            StringBuilder builder = new StringBuilder();
            builder.append("Retrieved saml messages and relay state from session");
            builder.append("saml Request message=").append(samlRequestMessage);
            builder.append("::").append("SAMLResponseMessage=");
            builder.append(samlResponseMessage).append(":").append("relay state=").append(relayState);

            builder.append("Signature=").append(signature).append("::sigAlg=").append(sigAlg);
            logger.trace(builder.toString());
        }

        if (isNotNull(samlRequestMessage))
            session.removeNote(GeneralConstants.SAML_REQUEST_KEY);
        if (isNotNull(samlResponseMessage))
            session.removeNote(GeneralConstants.SAML_RESPONSE_KEY);

        if (isNotNull(relayState))
            session.removeNote(GeneralConstants.RELAY_STATE);

        if (isNotNull(signature))
            session.removeNote(GeneralConstants.SAML_SIGNATURE_REQUEST_KEY);
        if (isNotNull(sigAlg))
            session.removeNote(GeneralConstants.SAML_SIG_ALG_REQUEST_KEY);
    }

    protected void sendErrorResponseToSP(String referrer, Response response, String relayState, IDPWebRequestUtil webRequestUtil)
            throws ServletException, IOException, ConfigurationException {

        logger.trace("About to send error response to SP:" + referrer);

        String contextPath = getContextPath();

        Document samlResponse = webRequestUtil.getErrorResponse(referrer, JBossSAMLURIConstants.STATUS_RESPONDER.get(),
                getIdentityURL(), this.idpConfiguration.isSupportsSignature());
        try {

            WebRequestUtilHolder holder = webRequestUtil.getHolder();
            holder.setResponseDoc(samlResponse).setDestination(referrer).setRelayState(relayState)
                    .setAreWeSendingRequest(false).setPrivateKey(null).setSupportSignature(false).setServletResponse(response);
            holder.setPostBindingRequested(webRequestUtil.hasSAMLRequestInPostProfile());

            if (this.idpConfiguration.isSupportsSignature()) {
                holder.setPrivateKey(keyManager.getSigningKey()).setSupportSignature(true);
            }

            holder.setStrictPostBinding(this.idpConfiguration.isStrictPostBinding());

            if (holder.isPostBinding())
                recycle(response);

            if (enableAudit) {
                PicketLinkAuditEvent auditEvent = new PicketLinkAuditEvent(AuditLevel.INFO);
                auditEvent.setType(PicketLinkAuditEventType.ERROR_RESPONSE_TO_SP);
                auditEvent.setWhoIsAuditing(contextPath);
                auditEvent.setDestination(referrer);
                auditHelper.audit(auditEvent);
            }
            webRequestUtil.send(holder);
        } catch (ParsingException e1) {
            throw new ServletException(e1);
        } catch (GeneralSecurityException e) {
            throw new ServletException(e);
        }
    }

    /**
     * <p>
     * Initializes the {@link IdentityServer}.
     * </p>
     */
    protected void initIdentityServer() {
        // The Identity Server on the servlet context gets set
        // in the implementation of IdentityServer
        // Create an Identity Server and set it on the context
        IdentityServer identityServer = (IdentityServer) getContext().getServletContext().getAttribute(
                GeneralConstants.IDENTITY_SERVER);
        if (identityServer == null) {
            identityServer = new IdentityServer();
            getContext().getServletContext().setAttribute(GeneralConstants.IDENTITY_SERVER, identityServer);
            if (StringUtil.isNotNull(this.idpConfiguration.getIdentityParticipantStack())) {
                try {
                    Class<?> clazz = SecurityActions.loadClass(getClass(), this.idpConfiguration.getIdentityParticipantStack());
                    if (clazz == null)
                        throw logger.classNotLoadedError(this.idpConfiguration.getIdentityParticipantStack());

                    identityServer.setStack((IdentityParticipantStack) clazz.newInstance());
                } catch (Exception e) {
                    logger.samlIDPUnableToSetParticipantStackUsingDefault(e);
                }
            }
        }
    }

    /**
     * <p>
     * Initialize the Handlers chain.
     * </p>
     *
     * @throws LifecycleException
     */
    protected void initHandlersChain() throws LifecycleException {
        Handlers handlers = null;

        try {
            if (picketLinkConfiguration != null) {
                handlers = picketLinkConfiguration.getHandlers();
            } else {
                // Get the handlers
                String handlerConfigFileName = GeneralConstants.HANDLER_CONFIG_FILE_LOCATION;
                handlers = ConfigurationUtil.getHandlers(getContext().getServletContext().getResourceAsStream(
                        handlerConfigFileName));
            }

            // Get the chain from config
            String handlerChainClass = handlers.getHandlerChainClass();

            if (StringUtil.isNullOrEmpty(handlerChainClass))
                chain = SAML2HandlerChainFactory.createChain();
            else {
                try {
                    chain = SAML2HandlerChainFactory.createChain(handlerChainClass);
                } catch (ProcessingException e1) {
                    throw new LifecycleException(e1);
                }
            }

            chain.addAll(HandlerUtil.getHandlers(handlers));

            Map<String, Object> chainConfigOptions = new HashMap<String, Object>();
            chainConfigOptions.put(GeneralConstants.ROLE_GENERATOR, roleGenerator);
            chainConfigOptions.put(GeneralConstants.CONFIGURATION, idpConfiguration);
            if (this.keyManager != null){
                chainConfigOptions.put(GeneralConstants.KEYPAIR, keyManager.getSigningKeyPair());
                String certAlias = (String) keyManager.getAdditionalOption(GeneralConstants.X509CERTIFICATE);
                if( certAlias != null){
                    chainConfigOptions.put(GeneralConstants.X509CERTIFICATE, keyManager.getCertificate(certAlias));
                }
            }
            SAML2HandlerChainConfig handlerChainConfig = new DefaultSAML2HandlerChainConfig(chainConfigOptions);

            Set<SAML2Handler> samlHandlers = chain.handlers();

            for (SAML2Handler handler : samlHandlers) {
                handler.initChainConfig(handlerChainConfig);
            }
        } catch (Exception e) {
            logger.samlHandlerConfigurationError(e);
            throw new LifecycleException(e.getLocalizedMessage());
        }
    }

    protected void initKeyManager() throws LifecycleException {
        if (this.idpConfiguration.isSupportsSignature() || this.idpConfiguration.isEncrypt()) {
            KeyProviderType keyProvider = this.idpConfiguration.getKeyProvider();
            if (keyProvider == null)
                throw new LifecycleException(
                        logger.nullValueError("Key Provider is null for context=" + getContext().getName()));

            try {
                this.keyManager = CoreConfigUtil.getTrustKeyManager(keyProvider);

                List<AuthPropertyType> authProperties = CoreConfigUtil.getKeyProviderProperties(keyProvider);
                keyManager.setAuthProperties(authProperties);
                keyManager.setValidatingAlias(keyProvider.getValidatingAlias());
                //Special case when you need X509Data in SignedInfo
                if(authProperties != null){
                    for(AuthPropertyType authPropertyType: authProperties){
                        String key = authPropertyType.getKey();
                        if(GeneralConstants.X509CERTIFICATE.equals(key)){
                            //we need X509Certificate in SignedInfo. The value is the alias name
                            keyManager.addAdditionalOption(GeneralConstants.X509CERTIFICATE, authPropertyType.getValue());
                            break;
                        }
                    }
                }
            } catch (Exception e) {
                logger.trustKeyManagerCreationError(e);
                throw new LifecycleException(e.getLocalizedMessage());
            }

            logger.samlIDPSettingCanonicalizationMethod(idpConfiguration.getCanonicalizationMethod());

            XMLSignatureUtil.setCanonicalizationMethodType(idpConfiguration.getCanonicalizationMethod());

            logger.trace("Key Provider=" + keyProvider.getClassName());
        }
    }

    /**
     * <p>
     * Initializes the IDP configuration.
     * </p>
     */
    @SuppressWarnings("deprecation")
    protected void initIDPConfiguration() {
        String configFile = GeneralConstants.CONFIG_FILE_LOCATION;
        InputStream is = getContext().getServletContext().getResourceAsStream(configFile);

        // Work on the IDP Configuration
        if (configProvider != null) {
            try {
                if (is == null) {
                    // Try the older version
                    is = getContext().getServletContext().getResourceAsStream(GeneralConstants.DEPRECATED_CONFIG_FILE_LOCATION);

                    // Additionally parse the deprecated config file
                    if (is != null && configProvider instanceof AbstractSAMLConfigurationProvider) {
                        ((AbstractSAMLConfigurationProvider) configProvider).setConfigFile(is);
                    }
                } else {
                    // Additionally parse the consolidated config file
                    if (is != null && configProvider instanceof AbstractSAMLConfigurationProvider) {
                        ((AbstractSAMLConfigurationProvider) configProvider).setConsolidatedConfigFile(is);
                    }
                }

                picketLinkConfiguration = configProvider.getPicketLinkConfiguration();
                idpConfiguration = configProvider.getIDPConfiguration();
            } catch (ProcessingException e) {
                throw logger.samlIDPConfigurationError(e);
            } catch (ParsingException e) {
                throw logger.samlIDPConfigurationError(e);
            }
        }

        if (idpConfiguration == null) {
            if (is != null) {
                try {
                    picketLinkConfiguration = ConfigurationUtil.getConfiguration(is);
                    idpConfiguration = (IDPType) picketLinkConfiguration.getIdpOrSP();
                } catch (ParsingException e) {
                    logger.trace(e);
                    logger.samlIDPConfigurationError(e);
                }
            }

            if (is == null) {
                // Try the older version
                is = getContext().getServletContext().getResourceAsStream(GeneralConstants.DEPRECATED_CONFIG_FILE_LOCATION);
                if (is == null)
                    throw logger.configurationFileMissing(configFile);
                try {
                    idpConfiguration = ConfigurationUtil.getIDPConfiguration(is);
                } catch (ParsingException e) {
                    logger.samlIDPConfigurationError(e);
                }
            }
        }

        try {
            if (this.picketLinkConfiguration != null) {
                enableAudit = picketLinkConfiguration.isEnableAudit();

                // See if we have the system property enabled
                if (!enableAudit) {
                    String sysProp = SecurityActions.getSystemProperty(GeneralConstants.AUDIT_ENABLE, "NULL");
                    if (!"NULL".equals(sysProp)) {
                        enableAudit = Boolean.parseBoolean(sysProp);
                    }
                }

                if (enableAudit) {
                    if (auditHelper == null) {
                        String securityDomainName = PicketLinkAuditHelper.getSecurityDomainName(getContext()
                                .getServletContext());
                        auditHelper = new PicketLinkAuditHelper(securityDomainName);
                    }
                }
            }

            logger.trace("Identity Provider URL=" + getIdentityURL());

            // Get the attribute manager
            String attributeManager = idpConfiguration.getAttributeManager();
            if (attributeManager != null && !"".equals(attributeManager)) {
                Class<?> clazz = SecurityActions.loadClass(getClass(), attributeManager);
                if (clazz == null)
                    throw new RuntimeException(logger.classNotLoadedError(attributeManager));
                AttributeManager delegate = (AttributeManager) clazz.newInstance();
                this.attribManager.setDelegate(delegate);
            }

            // Get the role generator
            String roleGeneratorAttribute = idpConfiguration.getRoleGenerator();

            if (roleGeneratorAttribute != null && !"".equals(roleGeneratorAttribute)) {
                Class<?> clazz = SecurityActions.loadClass(getClass(), roleGeneratorAttribute);
                if (clazz == null)
                    throw new RuntimeException(logger.classNotLoadedError(roleGeneratorAttribute));
                roleGenerator = (RoleGenerator) clazz.newInstance();
            }

            // Read SP Metadata if provided
            List<EntityDescriptorType> entityDescriptors = CoreConfigUtil.getMetadataConfiguration(idpConfiguration,
                    getContext().getServletContext());
            if (entityDescriptors != null) {
                for (EntityDescriptorType entityDescriptorType : entityDescriptors) {
                    SPSSODescriptorType spSSODescriptor = CoreConfigUtil.getSPDescriptor(entityDescriptorType);
                    if (spSSODescriptor != null) {
                        spSSOMetadataMap.put(entityDescriptorType.getEntityID(), spSSODescriptor);
                    }
                }
            }
        } catch (Exception e) {
            throw logger.samlIDPConfigurationError(e);
        }

        initHostedURI();
    }

    /**
     * Initializes the STS configuration.
     */
    protected void initSTSConfiguration() {
        // if the sts configuration is present in the picketlink.xml then load it.
        if (this.picketLinkConfiguration != null && this.picketLinkConfiguration.getStsType() != null) {
            PicketLinkCoreSTS sts = PicketLinkCoreSTS.instance();
            sts.initialize(new PicketLinkSTSConfiguration(this.picketLinkConfiguration.getStsType()));
        } else {
            // Try to load from /WEB-INF/picketlink-sts.xml.

            // Ensure that the Core STS has the SAML20 Token Provider
            PicketLinkCoreSTS sts = PicketLinkCoreSTS.instance();
            // Let us look for a file
            String configPath = getContext().getServletContext().getRealPath("/WEB-INF/picketlink-sts.xml");
            File stsTokenConfigFile = configPath != null ? new File(configPath) : null;

            if (stsTokenConfigFile == null || stsTokenConfigFile.exists() == false) {
                logger.samlIDPInstallingDefaultSTSConfig();
                sts.installDefaultConfiguration();
            } else
                sts.installDefaultConfiguration(stsTokenConfigFile.toURI().toString());
        }
    }

    protected String getIdentityURL() {
        return this.idpConfiguration.getIdentityURL();
    }

    protected Context getContext() {
        return (Context) getContainer();
    }

    protected abstract String getContextPath();

    protected void recycle(Response response) {
        /**
         * Since the container finished authentication, it will try to locate index.jsp or index.html. We need to recycle
         * whatever is in the response object such that we direct it to the html that is being created as part of the HTTP/POST
         * binding
         */
        response.recycle();
    }

    protected String determineLoginType(boolean isSecure) {
        String result = JBossSAMLURIConstants.AC_PASSWORD.get();
        LoginConfig loginConfig = getContext().getLoginConfig();
        if (loginConfig != null) {
            String auth = loginConfig.getAuthMethod();
            if (StringUtil.isNotNull(auth)) {
                if ("CLIENT-CERT".equals(auth))
                    result = JBossSAMLURIConstants.AC_TLS_CLIENT.get();
                else if (isSecure)
                    result = JBossSAMLURIConstants.AC_PASSWORD_PROTECTED_TRANSPORT.get();
            }
        }
        return result;
    }

    protected void startPicketLink() throws LifecycleException {

        SystemPropertiesUtil.ensure();

        initIDPConfiguration();
        initSTSConfiguration();
        initKeyManager();
        initHandlersChain();
        initIdentityServer();

        // Add some keys to the attibutes
        String[] ak = new String[] { "mail", "cn", "commonname", "givenname", "surname", "employeeType", "employeeNumber",
                "facsimileTelephoneNumber" };

        this.attributeKeys.addAll(Arrays.asList(ak));
    }

    /**
     * Given a set of roles, create an attribute statement
     *
     * @param roles
     * @return
     */
    private SAML11AttributeStatementType createAttributeStatement(List<String> roles) {
        SAML11AttributeStatementType attrStatement = null;
        for (String role : roles) {
            if (attrStatement == null) {
                attrStatement = new SAML11AttributeStatementType();
            }
            SAML11AttributeType attr = new SAML11AttributeType("Role", URI.create("urn:picketlink:role"));
            attr.add(role);
            attrStatement.add(attr);
        }
        return attrStatement;
    }

    public void setAuditHelper(PicketLinkAuditHelper auditHelper) {
        this.auditHelper = auditHelper;
    }

    /**
     * We will ignore signatures of current SAMLRequest if SP Metadata are provided for current SP and if metadata specifies
     * that SAMLRequest is not signed for this SP.
     *
     * @param spIssuer
     * @return true if signature is not expected in SAMLRequest and so signature validation should be ignored
     */
    private Boolean willIgnoreSignatureOfCurrentRequest(String spIssuer) {
        SPSSODescriptorType currentSPMetadata = spSSOMetadataMap.get(spIssuer);

        if (currentSPMetadata == null) {
            return false;
        }

        Boolean isRequestSigned = currentSPMetadata.isAuthnRequestsSigned();

        logger.trace("Issuer: " + spIssuer + ", isRequestSigned: " + isRequestSigned);

        return !isRequestSigned;
    }

    private void initHostedURI() {
        String hostedURI = this.idpConfiguration.getHostedURI();

        if (isNullOrEmpty(hostedURI)) {
            hostedURI = "/hosted/";
        } else if (!hostedURI.contains(".") && !hostedURI.endsWith("/")) {
            // make sure the hosted uri have a slash at the end if it points to a directory
            hostedURI = hostedURI + "/";
        }

        this.idpConfiguration.setHostedURI(hostedURI);
    }

    private SSLAuthenticator getSSLAuthenticator() {
        if (this.sslAuthenticator == null) {
            this.sslAuthenticator = new SSLAuthenticator() {
                @Override
                public Valve getNext() {
                    return new ValveBase() {
                        @Override
                        public void invoke(Request request, Response response) throws IOException, ServletException {
                            // no-op
                        }
                    };
                }
            };

            this.sslAuthenticator.setContainer(getContainer());

            try {
                this.sslAuthenticator.start();
            } catch (LifecycleException e) {
                throw new RuntimeException("Error starting SSL authenticator.", e);
            }
        }

        return this.sslAuthenticator;
    }

}
TOP

Related Classes of org.picketlink.identity.federation.bindings.tomcat.idp.AbstractIDPValve

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.