org.jasig.portal.security.provider.saml.SAMLSession.java Source code

Java tutorial

Introduction

Here is the source code for org.jasig.portal.security.provider.saml.SAMLSession.java

Source

/**
 * Licensed to Jasig under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Jasig licenses this file to you 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.jasig.portal.security.provider.saml;

import org.apache.http.client.HttpClient;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpParams;
import org.w3c.dom.Document;

/**
 * This class is used to maintain the state of delegated SAML authentication
 * before, during, and after the authentication.  Please note that some of the
 * methods of this class are package-scoped.  This rather unusual scoping is
 * used to permit access to other classes, most notably {@link SAMLDelegatedAuthenticationService},
 * to methods in this class, but to keep those methods from the public API
 * documentation.
 *  
 * @author Adam Rybicki
 *
 */
public class SAMLSession {
    // The original assertion passed to the portal by the SP
    private final String samlAssertion;

    // HttpClient connection to the WSP.  This is what encapsulates the HTTP session with the WSP
    private final HttpClient wspHttpClient;

    private IdPEPRResolver idpResolver = null;

    // Parsed DOM of the SAML assertion
    private Document samlAssertionDom = null;

    // SSL Security options for the IdP
    private SSLSecurityWrapper idpSSL = new SSLSecurityImpl();

    // Entity ID os the portal
    private String portalEntityID;

    private boolean skipValidateIdp = false;

    /**
     * Public constructor that initializes the SAML session.  This sets up the
     * ThreadSafeConnectionManager because the connection interceptor will be
     * making a secondary connection to authenticate to the IdP while the
     * primary connection is blocked. 
     * 
     * @param samlAssertion SAML assertion that was passed to the portal for authentication
     * @param connectionManager The connection manager to use for the {@link HttpClient} used for making authenticated requests. The caller is responsible for the {@link ClientConnectionManager} lifecycle.
     * @param params the {@link HttpClient} configuration parameters to use.
     */
    public SAMLSession(String samlAssertion, ClientConnectionManager connectionManager, HttpParams params) {
        final DefaultHttpClient client = new DefaultHttpClient(connectionManager, params);
        client.addRequestInterceptor(new HttpRequestPreprocessor());
        client.addResponseInterceptor(new HttpRequestPostprocessor(this));
        this.wspHttpClient = client;
        this.samlAssertion = samlAssertion;
    }

    /**
     * Returns the same String representation of SAML assertion that was passed
     * to the constructor.
     * 
     * @return the SAML assertion
     */
    public String getSamlAssertion() {
        return samlAssertion;
    }

    /**
     * Returns the DOM representation of the SAML assertion.  Assertions are
     * usually digitally signed, so it is important to keep them unchanged.
     * @return the samlAssertionDom
     */
    public Document getSamlAssertionDom() {
        return samlAssertionDom;
    }

    /**
     * This method is intentionally package-scoped to maintain access to other
     * classed from this package, but to keep it from the public API documentation.
     */
    void setSamlAssertionDom(Document samlAssertionDom) {
        this.samlAssertionDom = samlAssertionDom;
    }

    /**
     * Returns the Apache Commons HTTP Client that is set up with an authenticated
     * session to the WSP.  Since the session management of the WSP is
     * WSP-specific, there is no way to guarantee that this HttpClient
     * will continue the session set up by the authentication process, but
     * because Apache Commons HTTP Client works much like a browser, it should
     * continue sending cookies that were established during authentication.
     * Shibboleth SP was specifically tested, and its session works as expected.
     * It is probably important to use the same scheme, host, and base context
     * as those used in the initial {@link Resource} passed during authentication.
     *  
     * @return wspHttpClient instance of Apache Commons HTTP Client {@link org.apache.http.client.HttpClient} class
     */
    public HttpClient getHttpClient() {
        return wspHttpClient;
    }

    /**
     * @return the idpResolver
     * @see setIdPResolver
     */
    public IdPEPRResolver getIdpResolver() {
        return idpResolver;
    }

    /**
     * Provide an implementation of the IdPEPRResolver interface to resolve the
     * IdP endpoint to which the delegated SAML authentication requests must be
     * presented.  The default implementation, {@link AssertionIdPResolver}
     * resolved the endpoint from SAML assertion.  Shibboleth IdP provides an
     * endpoint reference in the assertion.
     * 
     * @param idpResolver the implementation of the {@link IdPEPRResolver} interface
     */
    public void setIdpResolver(IdPEPRResolver idpResolver) {
        this.idpResolver = idpResolver;
    }

    /**
     * This method is used to specify the private key and certificate to use
     * to identify the client to the IdP.  The TLS layer will present the certificate
     * to the IdP.  Because, as far as the IdP is concerned, the portal and its SP
     * are one and the same, the parameters to this method will be the PEM-encoded
     * private key and certificate files that the SP uses.
     * 
     * @param pkFile file name of the PEM-encoded private key
     * @param certFile file name of the PEM-encoded certificate
     */
    public void setIdPClientPrivateKeyAndCert(String pkFile, String certFile) {
        this.idpSSL.setSSLClientPrivateKeyAndCert(pkFile, certFile);
    }

    /**
     * This method provides an alternative method of providing client TLS certificate
     * to send to the IdP to identify the client.
     * 
     * @param ks file name of Java KeyStore containing the certificate and private
     *           key to present to the IdP 
     * @param pass KeyStore password (must not be null)
     * @see #setIdPClientPrivateKeyAndCert()
     */
    public void setIdPClientKeystore(String ks, String pass) {
        this.idpSSL.setSSLClientKeystore(ks, pass);
    }

    /**
     * This method allows to specify a Java TrustStore of server X.509 certificates
     * to trust.  These may be either signing Certificate Authority (CA) certificates
     * of self-signed certificates for IdPs to trust.  Java normally trusts all
     * servers that present valid certificates signed by a recognized CA.  This method
     * allows to securely communicate with institution-specific IdP.
     * 
     * @param ks file name of a Java KeyStore
     * @param pass password to access the KeyStore
     */
    public void setIdPClientTrustStore(String ks, String pass) {
        this.idpSSL.setSSLTrustStore(ks, pass);
    }

    /**
     * This method allows to specify the public key(s) to verify and trust when
     * communicating with the IdP.  Shibboleth SP can provide the public key(s)
     * of the IdP to trust.  When the caller specifies the public key(s) to trust,
     * the connection to the IdP will not proceed if the IdP does not present
     * a matching public key.
     * 
     * @param publicKeys Base64-encoded public key(s) to verify before allowing
     *                   a connection to the IdP to proceed.
     */
    public void setIdPServerPublicKeys(String publicKeys) {
        this.idpSSL.setSSLServerPublicKeys(publicKeys);
    }

    /**
     * Returns an instance of {@link org.apache.http.conn.ssl.SSLSocketFactory}
     * suitable for use with the Apache Commons HTTP Client.  This socket factory
     * is set up with the previously set keys and/or certificates for communicating
     * with the IdP.
     * 
     * @return SSLSocketFactory suitable for use with the Apache Commons HTTP Client
     */
    public SSLSocketFactory getIdPSocketFactory() {
        return this.idpSSL.getSSLSocketFactory();
    }

    /**
     * Returns the portal's entityID.  This entityID is used to identify the
     * portal to the IdP when the IdP is contacted for delegated authentication.
     * 
     * @return the portalEntityID
     */
    public String getPortalEntityID() {
        return portalEntityID;
    }

    /**
     * Sets the portal's entityID.  This entityID is used to identify the
     * portal to the IdP when the IdP is contacted for delegated authentication.
     * 
     * @param portalEntityID the portalEntityID to set
     */
    public void setPortalEntityID(String portalEntityID) {
        this.portalEntityID = portalEntityID;
    }

    /**
     * @return If the IDP host name validation step should be skipped
     */
    public boolean isSkipValidateIdp() {
        return skipValidateIdp;
    }

    /**
     * Set if the IDP host name validation step should be skipped during authentication. This
     * is generally needed when using a WAYF since the target site will reference the WAYF and
     * not the IDP in the response.
     */
    public void setSkipValidateIdp(boolean skipValidateIdp) {
        this.skipValidateIdp = skipValidateIdp;
    }

}