be.fedict.eid.idp.sp.protocol.saml2.AuthenticationRequestServlet.java Source code

Java tutorial

Introduction

Here is the source code for be.fedict.eid.idp.sp.protocol.saml2.AuthenticationRequestServlet.java

Source

/*
 * eID Identity Provider Project.
 * Copyright (C) 2010 FedICT.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version
 * 3.0 as published by the Free Software Foundation.
 *
 * 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, see 
 * http://www.gnu.org/licenses/.
 */

package be.fedict.eid.idp.sp.protocol.saml2;

import java.io.IOException;
import java.security.KeyStore;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.opensaml.saml2.core.AuthnRequest;

import be.fedict.eid.idp.common.ServiceLocator;
import be.fedict.eid.idp.sp.protocol.saml2.spi.AuthenticationRequestService;

/**
 * Generates and sends out a SAML v2.0 Authentication Request.
 * <p/>
 * <p/>
 * Configuration can be provided either by providing:
 * <ul>
 * <li><tt>AuthenticationRequestService</tt>:
 * {@link AuthenticationRequestService} to provide the IdP protocol entry point,
 * SP response handling location, SP identity for signing the authentication
 * request, relay state, language</li>
 * </ul>
 * or by provinding:
 * <ul>
 * <li><tt>SPDestination</tt> or <tt>SPDestinationPage</tt>: Service Provider
 * destination that will handle the returned SAML2 response. One of the 2
 * parameters needs to be specified.</li>
 * <li><tt>IdPDestination</tt>: SAML2 entry point of the eID IdP.</li>
 * <li><tt>Language</tt>: optional language to display the eID IdP webapp in (if
 * available, else the browser's locale will be used).</li>
 * </ul>
 * 
 * @author Frank Cornelis
 * @author Wim Vandenhaute
 */
public class AuthenticationRequestServlet extends HttpServlet {

    private static final long serialVersionUID = 1L;

    private static final Log LOG = LogFactory.getLog(AuthenticationRequestServlet.class);

    public static final String REQUEST_ID_SESSION_ATTRIBUTE = AuthenticationRequestServlet.class.getName()
            + ".RequestID";
    public static final String REQUEST_ISSUER_SESSION_ATTRIBUTE = AuthenticationRequestServlet.class.getName()
            + ".RequestIssuer";
    public static final String RECIPIENT_SESSION_ATTRIBUTE = AuthenticationRequestServlet.class.getName()
            + ".Recipient";
    public static final String RELAY_STATE_SESSION_ATTRIBUTE = AuthenticationRequestServlet.class.getName()
            + ".RelayState";

    private static final String AUTHN_REQUEST_SERVICE_PARAM = "AuthenticationRequestService";
    private static final String IDP_DESTINATION_PARAM = "IdPDestination";
    private static final String SP_DESTINATION_PARAM = "SPDestination";
    private static final String SP_DESTINATION_PAGE_PARAM = SP_DESTINATION_PARAM + "Page";
    private static final String LANGUAGE_PARAM = "Language";

    private String idpDestination;
    private String spDestination;
    private String spDestinationPage;
    private String language;

    private ServiceLocator<AuthenticationRequestService> authenticationRequestServiceLocator;

    /**
     * {@inheritDoc}
     */
    @Override
    public void init(ServletConfig config) throws ServletException {

        this.idpDestination = config.getInitParameter(IDP_DESTINATION_PARAM);
        this.spDestination = config.getInitParameter(SP_DESTINATION_PARAM);
        this.spDestinationPage = config.getInitParameter(SP_DESTINATION_PAGE_PARAM);
        this.language = config.getInitParameter(LANGUAGE_PARAM);
        this.authenticationRequestServiceLocator = new ServiceLocator<AuthenticationRequestService>(
                AUTHN_REQUEST_SERVICE_PARAM, config);

        // validate necessary configuration params
        if (null == this.idpDestination && !this.authenticationRequestServiceLocator.isConfigured()) {
            throw new ServletException("need to provide either " + IDP_DESTINATION_PARAM + " or "
                    + AUTHN_REQUEST_SERVICE_PARAM + "(Class) init-params");
        }

        if (null == this.spDestination && null == this.spDestinationPage
                && !this.authenticationRequestServiceLocator.isConfigured()) {
            throw new ServletException("need to provide either " + SP_DESTINATION_PARAM + " or "
                    + SP_DESTINATION_PAGE_PARAM + " or " + AUTHN_REQUEST_SERVICE_PARAM + "(Class) init-param");
        }
    }

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        LOG.debug("doGet");

        String idpDestination;
        String relayState;
        KeyStore.PrivateKeyEntry spIdentity = null;
        String language;

        AuthenticationRequestService service = this.authenticationRequestServiceLocator.locateService();
        if (null != service) {
            idpDestination = service.getIdPDestination();
            relayState = service.getRelayState(request.getParameterMap());
            spIdentity = service.getSPIdentity();
            language = service.getLanguage();
        } else {
            idpDestination = this.idpDestination;
            relayState = null;
            language = this.language;
        }

        // sp-destination
        String spDestination = null;
        if (null != service) {
            spDestination = service.getSPDestination();
        }
        if (null == spDestination) {
            // not provided by the service, check web.xml...
            if (null != this.spDestination) {
                spDestination = this.spDestination;
            } else {
                spDestination = request.getScheme() + "://" + request.getServerName() + ":"
                        + request.getServerPort() + request.getContextPath() + this.spDestinationPage;
            }
        }

        // issuer
        String issuer = null;
        if (null != service) {
            issuer = service.getIssuer();
        }
        if (null == issuer) {
            issuer = spDestination;
        }

        // generate and send an authentication request
        AuthnRequest authnRequest = AuthenticationRequestUtil.sendRequest(issuer, idpDestination, spDestination,
                relayState, spIdentity, response, language);

        // save state on session
        setRequestIssuer(authnRequest.getIssuer().getValue(), request.getSession());
        setRequestId(authnRequest.getID(), request.getSession());
        setRecipient(authnRequest.getAssertionConsumerServiceURL(), request.getSession());
        setRelayState(relayState, request.getSession());
    }

    /*
     * State handling
     */
    private void setRequestId(String requestId, HttpSession session) {
        session.setAttribute(REQUEST_ID_SESSION_ATTRIBUTE, requestId);
    }

    /**
     * Used by the {@link AbstractAuthenticationResponseServlet} for validation
     * of the SAML v2.0 Response <tt>InResponseTo</tt> field.
     * 
     * @param httpSession
     *            the HTTP Session
     * @return the SAML v2.0 Authentication Request ID.
     */
    public static String getRequestId(HttpSession httpSession) {
        return (String) httpSession.getAttribute(REQUEST_ID_SESSION_ATTRIBUTE);
    }

    private void setRequestIssuer(String requestIssuer, HttpSession session) {
        session.setAttribute(REQUEST_ISSUER_SESSION_ATTRIBUTE, requestIssuer);
    }

    /**
     * Used by the {@link AbstractAuthenticationResponseServlet} for validation
     * of the SAML v2.0 Assertion Audience Restriction.
     * 
     * @param httpSession
     *            the HTTP Session
     * @return the SAML v2.0 Authentication Request ID.
     */
    public static String getRequestIssuer(HttpSession httpSession) {
        return (String) httpSession.getAttribute(REQUEST_ISSUER_SESSION_ATTRIBUTE);
    }

    private void setRecipient(String recipient, HttpSession session) {
        session.setAttribute(RECIPIENT_SESSION_ATTRIBUTE, recipient);
    }

    /**
     * Used by the {@link AbstractAuthenticationResponseServlet} for validation
     * of the SAML v2.0 Response <tt>AudienceRestriction</tt>.
     * 
     * @param httpSession
     *            the HTTP Session
     * @return the SAML v2.0 Authentication Request AssertionConsumerServiceURL
     */
    public static String getRecipient(HttpSession httpSession) {
        return (String) httpSession.getAttribute(RECIPIENT_SESSION_ATTRIBUTE);
    }

    private void setRelayState(String relayState, HttpSession session) {
        session.setAttribute(RELAY_STATE_SESSION_ATTRIBUTE, relayState);
    }

    /**
     * Used by the {@link AbstractAuthenticationResponseServlet} for validation
     * of the SAML v2.0 Response <tt>RelayState</tt>.
     * 
     * @param httpSession
     *            the HTTP Session
     * @return optional RelayState sent along with the SAML v2.0 Authentication
     *         Request
     */
    public static String getRelayState(HttpSession httpSession) {
        return (String) httpSession.getAttribute(RELAY_STATE_SESSION_ATTRIBUTE);
    }

}