# HG changeset patch # User gernotbelger # Date 1538062839 -7200 # Node ID d6d5ca6d4af0ed0ab6f0f5b663f148de13a26e3b # Parent ce13a2f072903b4e179d05c4ca6d1e2a4c9a807e Enabled logging of saml-group-name in log-ing logfile. Some cleanup/refaktoring. diff -r ce13a2f07290 -r d6d5ca6d4af0 gwt-client/src/main/java/org/dive4elements/river/client/client/services/UserCollectionsService.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/services/UserCollectionsService.java Mon Sep 17 19:07:57 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/services/UserCollectionsService.java Thu Sep 27 17:40:39 2018 +0200 @@ -11,6 +11,7 @@ import com.google.gwt.user.client.rpc.RemoteService; import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; +import org.dive4elements.river.client.server.auth.User; import org.dive4elements.river.client.shared.model.Collection; diff -r ce13a2f07290 -r d6d5ca6d4af0 gwt-client/src/main/java/org/dive4elements/river/client/server/LoginServlet.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/server/LoginServlet.java Mon Sep 17 19:07:57 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/LoginServlet.java Thu Sep 27 17:40:39 2018 +0200 @@ -10,16 +10,16 @@ import java.io.IOException; +import javax.servlet.ServletContext; import javax.servlet.ServletException; -import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; - import org.dive4elements.river.client.server.auth.Authentication; import org.dive4elements.river.client.server.auth.AuthenticationException; import org.dive4elements.river.client.server.auth.AuthenticationFactory; +import org.dive4elements.river.client.server.auth.User; import org.dive4elements.river.client.server.features.Features; public class LoginServlet extends AuthenticationServlet { @@ -27,12 +27,10 @@ private static Logger log = Logger.getLogger(LoginServlet.class); @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException - { - String encoding = req.getCharacterEncoding(); - String username = req.getParameter("username"); - String password = req.getParameter("password"); + protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { + final String encoding = req.getCharacterEncoding(); + final String username = req.getParameter("username"); + final String password = req.getParameter("password"); log.debug("Processing post request"); @@ -43,33 +41,29 @@ } try { - Authentication aresp = this.auth(username, password, encoding); + final Authentication aresp = this.auth(username, password, encoding); if (aresp == null || !aresp.isSuccess()) { log.debug("Authentication not successful"); this.redirectFailure(resp, req.getContextPath()); return; } - log.info("Authentication successfull."); - this.performLogin(req, resp, aresp.getUser()); + + final User user = aresp.getUser(); + final String userGroup = user.getUserGroup(); + + log.info(String.format("Authentication successfull: group = '%s'", userGroup)); + this.performLogin(req, resp, user); } - catch(AuthenticationException e) { + catch (final AuthenticationException e) { log.error(e.getMessage()); this.redirectFailure(resp, req.getContextPath(), e); } } - private Authentication auth( - String username, - String password, - String encoding - ) - throws AuthenticationException, IOException - { - ServletContext sc = this.getServletContext(); - Features features = (Features)sc.getAttribute( - Features.CONTEXT_ATTRIBUTE); - String auth = sc.getInitParameter("authentication"); - return AuthenticationFactory.getInstance(auth).auth(username, password, - encoding, features, sc); + private Authentication auth(final String username, final String password, final String encoding) throws AuthenticationException, IOException { + final ServletContext sc = this.getServletContext(); + final Features features = (Features) sc.getAttribute(Features.CONTEXT_ATTRIBUTE); + final String auth = sc.getInitParameter("authentication"); + return AuthenticationFactory.getInstance(auth).auth(username, password, encoding, features, sc); } -} +} \ No newline at end of file diff -r ce13a2f07290 -r d6d5ca6d4af0 gwt-client/src/main/java/org/dive4elements/river/client/server/SamlServlet.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/server/SamlServlet.java Mon Sep 17 19:07:57 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/SamlServlet.java Thu Sep 27 17:40:39 2018 +0200 @@ -12,32 +12,28 @@ import java.io.InputStream; import java.io.StringBufferInputStream; +import javax.servlet.ServletContext; import javax.servlet.ServletException; -import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; 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.saml.TicketValidator; import org.dive4elements.river.client.server.auth.saml.Assertion; +import org.dive4elements.river.client.server.auth.saml.TicketValidator; +import org.dive4elements.river.client.server.auth.was.Response; import org.dive4elements.river.client.server.features.Features; - public class SamlServlet extends AuthenticationServlet { private static Logger log = Logger.getLogger(SamlServlet.class); @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException - { - String encoding = req.getCharacterEncoding(); - String samlTicketXML = req.getParameter("saml"); + protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { + // final String encoding = req.getCharacterEncoding(); + final String samlTicketXML = req.getParameter("saml"); log.debug("Processing post request"); @@ -48,7 +44,7 @@ } try { - User user = this.auth(samlTicketXML); + final User user = this.auth(samlTicketXML); if (user == null) { log.debug("Authentication not successful"); this.redirectFailure(resp, req.getContextPath()); @@ -57,40 +53,33 @@ this.performLogin(req, resp, user); log.info("Authentication with existing SAML ticket."); } - catch(AuthenticationException e) { + catch (final AuthenticationException e) { log.error(e, e); this.redirectFailure(resp, req.getContextPath(), e); } } - private User auth(String samlTicketXML) - throws AuthenticationException, IOException - { - ServletContext sc = this.getServletContext(); + private User auth(final String samlTicketXML) throws AuthenticationException { + final ServletContext sc = this.getServletContext(); Assertion assertion = null; try { - String keyfile = - (String)sc.getInitParameter("saml-trusted-public-key"); - int timeEps = Integer.parseInt( - sc.getInitParameter("saml-time-tolerance")); - TicketValidator validator = - new TicketValidator(sc.getRealPath(keyfile), timeEps); + final String keyfile = sc.getInitParameter("saml-trusted-public-key"); + final int timeEps = Integer.parseInt(sc.getInitParameter("saml-time-tolerance")); + final TicketValidator validator = new TicketValidator(sc.getRealPath(keyfile), timeEps); - InputStream in = new StringBufferInputStream(samlTicketXML); + final InputStream in = new StringBufferInputStream(samlTicketXML); assertion = validator.checkTicket(new Base64InputStream(in)); } - catch (Exception e) { + catch (final Exception e) { log.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, samlTicketXML, - features.getFeatures(assertion.getRoles()), null); + if (assertion == null) + throw new AuthenticationException("Login failed."); + + final Features features = (Features) sc.getAttribute(Features.CONTEXT_ATTRIBUTE); + + return Response.createUser(null, samlTicketXML, assertion, features); } -} +} \ No newline at end of file diff -r ce13a2f07290 -r d6d5ca6d4af0 gwt-client/src/main/java/org/dive4elements/river/client/server/auth/Authentication.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/server/auth/Authentication.java Mon Sep 17 19:07:57 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/auth/Authentication.java Thu Sep 27 17:40:39 2018 +0200 @@ -12,12 +12,13 @@ */ public interface Authentication { - /** Returns true if the authentication was successfull + /** + * Returns true if the authentication was successfull */ - public boolean isSuccess(); + boolean isSuccess(); - /** Returns a new User object + /** + * Returns a new User object */ - public User getUser() throws AuthenticationException; - -} + User getUser() throws AuthenticationException; +} \ No newline at end of file diff -r ce13a2f07290 -r d6d5ca6d4af0 gwt-client/src/main/java/org/dive4elements/river/client/server/auth/DefaultUser.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/server/auth/DefaultUser.java Mon Sep 17 19:07:57 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/auth/DefaultUser.java Thu Sep 27 17:40:39 2018 +0200 @@ -10,62 +10,41 @@ import java.util.List; -public class DefaultUser -implements User -{ - protected String name; - protected String account; - protected String password; - protected String samlXML; - protected boolean expired; - protected List roles; - protected List features; - - public DefaultUser() { - } +public class DefaultUser implements User { + private final String name; + private final String account; + private final String password; + private final String samlXML; + private final boolean expired; + private final List roles; + private final List features; + private final String userGroup; - public DefaultUser( - String name, - String password, - String samlXML, - boolean expired, - List roles, - List features - ) { - this.name = name; + public DefaultUser(final String name, final String password, final String samlXML, final boolean expired, final List roles, + final List features, final String userGroup) { + this.name = name; this.password = password; - this.samlXML = samlXML; - this.expired = expired; - this.roles = roles; + this.samlXML = samlXML; + this.expired = expired; + this.roles = roles; this.features = features; - this.account = name; + this.account = name; + this.userGroup = userGroup; } @Override public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; + return this.name; } @Override public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; + return this.password; } @Override public boolean hasExpired() { - return expired; - } - - public void setExpired(boolean expired) { - this.expired = expired; + return this.expired; } @Override @@ -74,35 +53,27 @@ return this.roles; } - public void setRoles(List roles) { - this.roles = roles; + public List getAllowedFeatures() { + return this.features; } @Override - public boolean canUseFeature(String feature) { + public boolean canUseFeature(final String feature) { return this.features.contains(feature); } - public void setAllowedFeatures(List features) { - this.features = features; - } - @Override public String getAccount() { return this.account; } - public void setAccount(String account) { - this.account = account; - } - @Override public String getSamlXMLBase64() { return this.samlXML; } - public void setSamlXMLBase64(String samlXML) { - this.samlXML = samlXML; + @Override + public String getUserGroup() { + return this.userGroup; } -} -// vim:set ts=4 sw=4 si et fenc=utf8 tw=80: +} \ No newline at end of file diff -r ce13a2f07290 -r d6d5ca6d4af0 gwt-client/src/main/java/org/dive4elements/river/client/server/auth/User.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/server/auth/User.java Mon Sep 17 19:07:57 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/auth/User.java Thu Sep 27 17:40:39 2018 +0200 @@ -18,40 +18,41 @@ /** * Returns the username as String */ - public String getName(); + String getName(); /** * Returns the password of the user as String */ - public String getPassword(); + String getPassword(); /** * Returns True if the authentication for the user * has expired. */ - public boolean hasExpired(); + boolean hasExpired(); /** * Returns a list of roles corresponsing the the user */ - public List getRoles(); + List getRoles(); /** * Returns true if the user is allowed access the feature */ - public boolean canUseFeature(String feature); + boolean canUseFeature(String feature); /** * Returns the users account name */ - public String getAccount(); + String getAccount(); /** * Returns the SAML ticket for single sign-on. * @return The SAML ticket in base64 encoded XML. null if no ticket * is available. */ - public String getSamlXMLBase64(); -} -// vim:set ts=4 sw=4 si et fenc=utf8 tw=80: + String getSamlXMLBase64(); + + String getUserGroup(); +} \ No newline at end of file diff -r ce13a2f07290 -r d6d5ca6d4af0 gwt-client/src/main/java/org/dive4elements/river/client/server/auth/plain/Authenticator.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/server/auth/plain/Authenticator.java Mon Sep 17 19:07:57 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/auth/plain/Authenticator.java Thu Sep 27 17:40:39 2018 +0200 @@ -65,7 +65,7 @@ return isSuccess() ? new DefaultUser( user, password, null, false, roles, - this.features.getFeatures(roles)) + this.features.getFeatures(roles), null) : null; } } // class Authentication diff -r ce13a2f07290 -r d6d5ca6d4af0 gwt-client/src/main/java/org/dive4elements/river/client/server/auth/saml/User.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/server/auth/saml/User.java Mon Sep 17 19:07:57 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/* 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.auth.saml; - -import java.util.List; - -import org.dive4elements.river.client.server.auth.DefaultUser; - -public class User -extends DefaultUser -implements org.dive4elements.river.client.server.auth.User { - - private Assertion assertion; - - public User(Assertion assertion, String samlXML, List features, - String password) { - this.setName(assertion.getNameID()); - this.setAccount(assertion.getNameID()); - this.setRoles(assertion.getRoles()); - this.assertion = assertion; - this.setSamlXMLBase64(samlXML); - this.setAllowedFeatures(features); - this.setPassword(password); - } - - @Override - public boolean hasExpired() { - // We could check the validity dates of the assertion here, but - // when using this for Single-Sign-On this would lead to the - // code in GGInAFilter to re-authenticate with the password - // stored in the User object, which isn't known in the case of - // Single-Sign-On. - return false; - } -} - -// vim:set ts=4 sw=4 si et fenc=utf8 tw=80: diff -r ce13a2f07290 -r d6d5ca6d4af0 gwt-client/src/main/java/org/dive4elements/river/client/server/auth/was/Authenticator.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/server/auth/was/Authenticator.java Mon Sep 17 19:07:57 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/auth/was/Authenticator.java Thu Sep 27 17:40:39 2018 +0200 @@ -66,7 +66,7 @@ (String)context.getInitParameter("saml-trusted-public-key"); String timeEpsilon = context.getInitParameter( "saml-time-tolerance"); - return new Response(entity, username, password, features, + return new Response(entity, password, features, context.getRealPath(trustedKey), timeEpsilon); } } diff -r ce13a2f07290 -r d6d5ca6d4af0 gwt-client/src/main/java/org/dive4elements/river/client/server/auth/was/Response.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/server/auth/was/Response.java Mon Sep 17 19:07:57 2018 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/auth/was/Response.java Thu Sep 27 17:40:39 2018 +0200 @@ -14,50 +14,42 @@ import java.util.List; import org.apache.commons.codec.binary.Base64InputStream; - import org.apache.http.HttpEntity; import org.apache.http.util.EntityUtils; - import org.apache.log4j.Logger; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - import org.dive4elements.artifacts.httpclient.utils.XMLUtils; import org.dive4elements.river.client.server.auth.Authentication; import org.dive4elements.river.client.server.auth.AuthenticationException; +import org.dive4elements.river.client.server.auth.DefaultUser; +import org.dive4elements.river.client.server.auth.User; import org.dive4elements.river.client.server.auth.saml.Assertion; -import org.dive4elements.river.client.server.auth.saml.XPathUtils; import org.dive4elements.river.client.server.auth.saml.TicketValidator; -import org.dive4elements.river.client.server.auth.saml.User; - +import org.dive4elements.river.client.server.auth.saml.XPathUtils; import org.dive4elements.river.client.server.features.Features; - +import org.w3c.dom.Document; +import org.w3c.dom.Element; public class Response implements Authentication { private static Logger log = Logger.getLogger(Response.class); - private Element root; - private String samlTicketXML; + private final Element root; + private final String samlTicketXML; private Assertion assertion; - private String username; - private String password; - private Features features; - private String trustedKeyFile; - private String timeEpsilon; + private final String password; + private final Features features; + private final String trustedKeyFile; + private final String timeEpsilon; - - public Response(HttpEntity entity, String username, String password, - Features features, String trustedKeyFile, String timeEpsilon) - throws AuthenticationException, IOException { + public Response(final HttpEntity entity, final String password, final Features features, final String trustedKeyFile, + final String timeEpsilon) throws AuthenticationException, IOException { if (entity == null) { throw new ServiceException("Invalid response"); } - String contenttype = entity.getContentType().getValue(); - String samlTicketXML = EntityUtils.toString(entity); + final String contenttype = entity.getContentType().getValue(); + final String samlTicketXML = EntityUtils.toString(entity); InputStream in = new StringBufferInputStream(samlTicketXML); @@ -66,18 +58,15 @@ in = new Base64InputStream(in); } - Document doc = XMLUtils.readDocument(in); - Element root = doc.getDocumentElement(); - String rname = root.getTagName(); + final Document doc = XMLUtils.readDocument(in); + final Element root = doc.getDocumentElement(); + final String rname = root.getTagName(); - if (rname != null && rname.equals("ServiceExceptionReport")) { - throw new ServiceException(XPathUtils.xpathString(root, - "ServiceException")); - } + if (rname != null && rname.equals("ServiceExceptionReport")) + throw new ServiceException(XPathUtils.xpathString(root, "ServiceException")); this.samlTicketXML = samlTicketXML; this.root = root; - this.username = username; this.password = password; this.features = features; this.trustedKeyFile = trustedKeyFile; @@ -86,25 +75,22 @@ @Override public boolean isSuccess() { - String status = getStatus(); + final String status = getStatus(); return status != null && status.equals("samlp:Success"); } - public String getStatus() { - return XPathUtils.xpathString(this.root, - "./samlp:Status/samlp:StatusCode/@Value"); + private String getStatus() { + return XPathUtils.xpathString(this.root, "./samlp:Status/samlp:StatusCode/@Value"); } - - public Assertion getAssertion() { + private Assertion getAssertion() { if (this.assertion == null && this.root != null) { try { - int timeEps = Integer.parseInt(this.timeEpsilon); - TicketValidator validator = - new TicketValidator(this.trustedKeyFile, timeEps); + final int timeEps = Integer.parseInt(this.timeEpsilon); + final TicketValidator validator = new TicketValidator(this.trustedKeyFile, timeEps); this.assertion = validator.checkTicket(this.root); } - catch (Exception e) { + catch (final Exception e) { log.error(e.getLocalizedMessage(), e); } } @@ -113,16 +99,32 @@ @Override public User getUser() throws AuthenticationException { - Assertion assertion = this.getAssertion(); - if (assertion == null) { - throw new AuthenticationException( - "Response doesn't contain an assertion"); - } - List features = this.features.getFeatures( - this.assertion.getRoles()); - log.debug("User " + this.username + " with features " + features + - " successfully authenticated."); - return new User(assertion, this.samlTicketXML, features, this.password); + final Assertion assertion = this.getAssertion(); + if (assertion == null) + throw new AuthenticationException("Response doesn't contain an assertion"); + + final DefaultUser user = createUser(this.password, this.samlTicketXML, assertion, this.features); + + log.debug("User " + user.getName() + " with features " + user.getAllowedFeatures() + " successfully authenticated."); + + return user; } -} -// vim: set si et fileencoding=utf-8 ts=4 sw=4 tw=80: + + public static DefaultUser createUser(final String password, final String samlTicketXML, final Assertion assertion, final Features features) { + final List roles = assertion.getRoles(); + + final List allowedFeatures = features.getFeatures(roles); + + // We could check the validity dates of the assertion here, but + // when using this for Single-Sign-On this would lead to the + // code in GGInAFilter to re-authenticate with the password + // stored in the User object, which isn't known in the case of + // Single-Sign-On. + final boolean expired = false; + + final String username = assertion.getNameID(); + final String userGroup = assertion.getGroupName(); + + return new DefaultUser(username, password, samlTicketXML, expired, roles, allowedFeatures, userGroup); + } +} \ No newline at end of file diff -r ce13a2f07290 -r d6d5ca6d4af0 gwt-client/src/test/java/test/AbstractModuleRunner.java --- a/gwt-client/src/test/java/test/AbstractModuleRunner.java Mon Sep 17 19:07:57 2018 +0200 +++ b/gwt-client/src/test/java/test/AbstractModuleRunner.java Thu Sep 27 17:40:39 2018 +0200 @@ -111,7 +111,7 @@ } private static String makeUserUuid(final String serverUrl) throws ConnectionException { - final User user = new DefaultUser(USERNAME, PASSWORD, null, false, new ArrayList(), new ArrayList()); + final User user = new DefaultUser(USERNAME, PASSWORD, null, false, new ArrayList(), new ArrayList(), null); final UserClient userClient = new UserClient(serverUrl); Element userElement;