view gwt-client/src/main/java/org/dive4elements/river/client/server/SamlServlet.java @ 5950:38d161edba77

Add SamlServlet to implement actual login via SAML Ticket. This is the main part of single-sign-on for flys from issue1265. SamlServlet is an adapted copy of LoginServlet. The code shared by both classes will be extracted into a base class later.
author Bernhard Herzog <bh@intevation.de>
date Wed, 08 May 2013 17:56:14 +0200
parents
children 24dc13ac8e6c
line wrap: on
line source
/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
 * Software engineering by Intevation GmbH
 *
 * This file is Free Software under the GNU AGPL (>=v3) 
 * and comes with ABSOLUTELY NO WARRANTY! Check out the
 * documentation coming with Dive4Elements River for details. 
 */

package org.dive4elements.river.client.server;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringBufferInputStream;

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

import org.apache.commons.codec.binary.Base64InputStream;

import org.apache.log4j.Logger;

import org.dive4elements.river.client.server.auth.AuthenticationException;
import org.dive4elements.river.client.server.auth.User;
import org.dive4elements.river.client.server.auth.UserClient;
import org.dive4elements.river.client.server.auth.saml.TicketValidator;
import org.dive4elements.river.client.server.auth.saml.Assertion;
import org.dive4elements.river.client.server.features.Features;


public class SamlServlet extends HttpServlet {

    private static Logger logger = Logger.getLogger(SamlServlet.class);

    private static final String FLYS_PAGE = "FLYS.html";
    private static final String LOGIN_PAGE = "login.jsp";

    private void redirectFailure(HttpServletResponse resp, String path)
        throws IOException {
        resp.sendRedirect(path + "/" + LOGIN_PAGE);
    }

    private void redirectFailure(HttpServletResponse resp, String path,
            Exception e) throws IOException {
        this.redirectFailure(resp, path, e.getMessage());
    }

    private void redirectFailure(HttpServletResponse resp, String path,
            String message) throws IOException {
        resp.sendRedirect(path + "/" + LOGIN_PAGE + "?error=" + message);
    }

    private void redirectSuccess(HttpServletResponse resp, String path,
            String uri) throws IOException {
        if (uri == null) {
            String redirecturl = getServletContext().getInitParameter("redirect-url");
            if (redirecturl == null) {
                redirecturl = FLYS_PAGE;
            }
            uri = "/" + redirecturl;
        }
        resp.sendRedirect(uri);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException {
        logger.debug("Processing get request");
        this.redirectFailure(resp, req.getContextPath());
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException
    {
        String encoding = req.getCharacterEncoding();
        String samlTicketXML = req.getParameter("samlTicket");

        logger.debug("Processing post request");

        if (samlTicketXML == null) {
            logger.debug("No saml ticket provided");
            this.redirectFailure(resp, req.getContextPath());
            return;
        }

        try {
            User user = this.auth(samlTicketXML);
            if (user == null) {
                logger.debug("Authentication not successful");
                this.redirectFailure(resp, req.getContextPath());
                return;
            }

            String url = getServletContext().getInitParameter("server-url");
            UserClient client = new UserClient(url);
            if (!client.userExists(user)) {
                logger.debug("Creating db user");
                if (!client.createUser(user)) {
                    this.redirectFailure(resp, req.getContextPath(),
                            "Could not create new user");
                    return;
                }
            }

            HttpSession session = req.getSession();
            session.setAttribute("user", user);

            String uri = (String)session.getAttribute("requesturi");

            this.redirectSuccess(resp, req.getContextPath(), uri);
        }
        catch(AuthenticationException e) {
            logger.error(e, e);
            this.redirectFailure(resp, req.getContextPath(), e);
        }
    }

    private User auth(String samlTicketXML)
        throws AuthenticationException, IOException
    {
        ServletContext sc = this.getServletContext();

        Assertion assertion = null;
        try {
            String keyfile =
                (String)sc.getInitParameter("saml-trusted-public-key");
            TicketValidator validator =
                new TicketValidator(sc.getRealPath(keyfile));

            InputStream in = new StringBufferInputStream(samlTicketXML);
            assertion = validator.checkTicket(new Base64InputStream(in));
        }
        catch (Exception e) {
            logger.error(e.getLocalizedMessage(), e);
        }
        if (assertion == null) {
            throw new AuthenticationException("Login failed.");
        }

        Features features = (Features)sc.getAttribute(Features.CONTEXT_ATTRIBUTE);
        return new org.dive4elements.river.client.server.auth.saml.User(
            assertion, features.getFeatures(assertion.getRoles()), null);
    }
}

http://dive4elements.wald.intevation.org