bh@5950: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde bh@5950: * Software engineering by Intevation GmbH bh@5950: * bh@5950: * This file is Free Software under the GNU AGPL (>=v3) bh@5950: * and comes with ABSOLUTELY NO WARRANTY! Check out the bh@5950: * documentation coming with Dive4Elements River for details. bh@5950: */ bh@5950: bh@5950: package org.dive4elements.river.client.server; bh@5950: bh@5950: import java.io.IOException; bh@5950: import java.io.InputStream; bh@5950: import java.io.StringBufferInputStream; bh@5950: bh@5950: import javax.servlet.ServletException; bh@5950: import javax.servlet.ServletContext; bh@5950: import javax.servlet.http.HttpServlet; bh@5950: import javax.servlet.http.HttpServletRequest; bh@5950: import javax.servlet.http.HttpServletResponse; bh@5950: import javax.servlet.http.HttpSession; bh@5950: bh@5950: import org.apache.commons.codec.binary.Base64InputStream; bh@5950: bh@5950: import org.apache.log4j.Logger; bh@5950: bh@5950: import org.dive4elements.river.client.server.auth.AuthenticationException; bh@5950: import org.dive4elements.river.client.server.auth.User; bh@5950: import org.dive4elements.river.client.server.auth.UserClient; bh@5950: import org.dive4elements.river.client.server.auth.saml.TicketValidator; bh@5950: import org.dive4elements.river.client.server.auth.saml.Assertion; bh@5950: import org.dive4elements.river.client.server.features.Features; bh@5950: bh@5950: bh@5950: public class SamlServlet extends HttpServlet { bh@5950: bh@5950: private static Logger logger = Logger.getLogger(SamlServlet.class); bh@5950: bh@5950: private static final String FLYS_PAGE = "FLYS.html"; bh@5950: private static final String LOGIN_PAGE = "login.jsp"; bh@5950: bh@5950: private void redirectFailure(HttpServletResponse resp, String path) bh@5950: throws IOException { bh@5950: resp.sendRedirect(path + "/" + LOGIN_PAGE); bh@5950: } bh@5950: bh@5950: private void redirectFailure(HttpServletResponse resp, String path, bh@5950: Exception e) throws IOException { bh@5950: this.redirectFailure(resp, path, e.getMessage()); bh@5950: } bh@5950: bh@5950: private void redirectFailure(HttpServletResponse resp, String path, bh@5950: String message) throws IOException { bh@5950: resp.sendRedirect(path + "/" + LOGIN_PAGE + "?error=" + message); bh@5950: } bh@5950: bh@5950: private void redirectSuccess(HttpServletResponse resp, String path, bh@5950: String uri) throws IOException { bh@5950: if (uri == null) { bh@5950: String redirecturl = getServletContext().getInitParameter("redirect-url"); bh@5950: if (redirecturl == null) { bh@5950: redirecturl = FLYS_PAGE; bh@5950: } bh@5950: uri = "/" + redirecturl; bh@5950: } bh@5950: resp.sendRedirect(uri); bh@5950: } bh@5950: bh@5950: @Override bh@5950: protected void doGet(HttpServletRequest req, HttpServletResponse resp) bh@5950: throws ServletException, IOException { bh@5950: logger.debug("Processing get request"); bh@5950: this.redirectFailure(resp, req.getContextPath()); bh@5950: } bh@5950: bh@5950: @Override bh@5950: protected void doPost(HttpServletRequest req, HttpServletResponse resp) bh@5950: throws ServletException, IOException bh@5950: { bh@5950: String encoding = req.getCharacterEncoding(); bh@5950: String samlTicketXML = req.getParameter("samlTicket"); bh@5950: bh@5950: logger.debug("Processing post request"); bh@5950: bh@5950: if (samlTicketXML == null) { bh@5950: logger.debug("No saml ticket provided"); bh@5950: this.redirectFailure(resp, req.getContextPath()); bh@5950: return; bh@5950: } bh@5950: bh@5950: try { bh@5950: User user = this.auth(samlTicketXML); bh@5950: if (user == null) { bh@5950: logger.debug("Authentication not successful"); bh@5950: this.redirectFailure(resp, req.getContextPath()); bh@5950: return; bh@5950: } bh@5950: bh@5950: String url = getServletContext().getInitParameter("server-url"); bh@5950: UserClient client = new UserClient(url); bh@5950: if (!client.userExists(user)) { bh@5950: logger.debug("Creating db user"); bh@5950: if (!client.createUser(user)) { bh@5950: this.redirectFailure(resp, req.getContextPath(), bh@5950: "Could not create new user"); bh@5950: return; bh@5950: } bh@5950: } bh@5950: bh@5950: HttpSession session = req.getSession(); bh@5950: session.setAttribute("user", user); bh@5950: bh@5950: String uri = (String)session.getAttribute("requesturi"); bh@5950: bh@5950: this.redirectSuccess(resp, req.getContextPath(), uri); bh@5950: } bh@5950: catch(AuthenticationException e) { bh@5950: logger.error(e, e); bh@5950: this.redirectFailure(resp, req.getContextPath(), e); bh@5950: } bh@5950: } bh@5950: bh@5950: private User auth(String samlTicketXML) bh@5950: throws AuthenticationException, IOException bh@5950: { bh@5950: ServletContext sc = this.getServletContext(); bh@5950: bh@5950: Assertion assertion = null; bh@5950: try { bh@5950: String keyfile = bh@5950: (String)sc.getInitParameter("saml-trusted-public-key"); bh@5950: TicketValidator validator = bh@5950: new TicketValidator(sc.getRealPath(keyfile)); bh@5950: bh@5950: InputStream in = new StringBufferInputStream(samlTicketXML); bh@5950: assertion = validator.checkTicket(new Base64InputStream(in)); bh@5950: } bh@5950: catch (Exception e) { bh@5950: logger.error(e.getLocalizedMessage(), e); bh@5950: } bh@5950: if (assertion == null) { bh@5950: throw new AuthenticationException("Login failed."); bh@5950: } bh@5950: bh@5950: Features features = (Features)sc.getAttribute(Features.CONTEXT_ATTRIBUTE); bh@5950: return new org.dive4elements.river.client.server.auth.saml.User( bh@5950: assertion, features.getFeatures(assertion.getRoles()), null); bh@5950: } bh@5950: }