Mercurial > dive4elements > river
changeset 8839:2c8259176c46
Add configurable time tolerance to SAML ticket validation.
This allows e.g. to account for time skew between the ISP and
the server this servlet is run on.
author | Tom Gottfried <tom@intevation.de> |
---|---|
date | Wed, 28 Jun 2017 20:09:53 +0200 |
parents | 1fa03f3c9d3d |
children | 98a3cf810916 |
files | gwt-client/src/main/java/org/dive4elements/river/client/server/auth/saml/Assertion.java gwt-client/src/main/java/org/dive4elements/river/client/server/auth/saml/TicketValidator.java gwt-client/src/main/java/org/dive4elements/river/client/server/auth/was/Authenticator.java gwt-client/src/main/java/org/dive4elements/river/client/server/auth/was/Response.java gwt-client/src/main/webapp/WEB-INF/web.xml |
diffstat | 5 files changed, 34 insertions(+), 13 deletions(-) [+] |
line wrap: on
line diff
--- a/gwt-client/src/main/java/org/dive4elements/river/client/server/auth/saml/Assertion.java Tue May 30 12:51:42 2017 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/auth/saml/Assertion.java Wed Jun 28 20:09:53 2017 +0200 @@ -48,7 +48,6 @@ private static final String ATTR_CONT_ROLE = "urn:conterra:names:sdi-suite:policy:attribute:role"; - public Assertion(Element assertion) { this.assertion = assertion; this.roles = new LinkedList<String>(); @@ -174,14 +173,15 @@ * Returns whether the ticket to which the assertion belongs is * valid at the time the method is called. The method returns true, * if both dates (notbefore and notonorafter) have been determined - * successfully and the current date/time is between both. + * successfully and the current date/time is between both (with given + * tolerance). * @return Whether the ticket is valid now. */ - public boolean isValidNow() { + public boolean isValidNow(int timeEps) { Date now = new Date(); return (this.notbefore != null && this.notonorafter != null - && now.after(this.notbefore) - && !this.notonorafter.before(now)); + && now.after(new Date(this.notbefore.getTime() - timeEps)) + && now.before(new Date(this.notonorafter.getTime() + timeEps))); } } // vim: set fileencoding=utf-8 ts=4 sw=4 et si tw=80:
--- a/gwt-client/src/main/java/org/dive4elements/river/client/server/auth/saml/TicketValidator.java Tue May 30 12:51:42 2017 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/auth/saml/TicketValidator.java Wed Jun 28 20:09:53 2017 +0200 @@ -48,11 +48,18 @@ private Key trustedKey; /** + * Tolerance in milliseconds for validation based on NotBefore and + * NotOnOrAfter of the SAML ticket + */ + private int timeEps; + + /** * Creates a new TicketValidator from a trusted key. * @param trustedKey The trusted key for the signature checks. */ - public TicketValidator(Key trustedKey) { + public TicketValidator(Key trustedKey, int timeEps) { this.trustedKey = trustedKey; + this.timeEps = timeEps; } /** @@ -61,9 +68,10 @@ * @param filename The filename of the X509 certificate containing * the trusted public key. */ - public TicketValidator(String filename) throws IOException, - CertificateException { + public TicketValidator(String filename, int timeEps) + throws IOException, CertificateException { this.trustedKey = loadKey(filename); + this.timeEps = timeEps; } /** @@ -107,10 +115,11 @@ } Assertion assertion = new Assertion(assertionElement); - if (!assertion.isValidNow()) { + if (!assertion.isValidNow(this.timeEps)) { log.error("Ticket is not valid now" + " (NotBefore: " + assertion.getFrom() - + ", NotOnOrAfter: " + assertion.getUntil()); + + ", NotOnOrAfter: " + assertion.getUntil() + + ", Tolerance (milliseconds): " + this.timeEps); return null; }
--- a/gwt-client/src/main/java/org/dive4elements/river/client/server/auth/was/Authenticator.java Tue May 30 12:51:42 2017 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/auth/was/Authenticator.java Wed Jun 28 20:09:53 2017 +0200 @@ -64,8 +64,10 @@ else { String trustedKey = (String)context.getInitParameter("saml-trusted-public-key"); + String timeEpsilon = context.getInitParameter( + "saml-time-tolerance"); return new Response(entity, username, password, features, - context.getRealPath(trustedKey)); + context.getRealPath(trustedKey), timeEpsilon); } } catch(GeneralSecurityException e) {
--- a/gwt-client/src/main/java/org/dive4elements/river/client/server/auth/was/Response.java Tue May 30 12:51:42 2017 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/auth/was/Response.java Wed Jun 28 20:09:53 2017 +0200 @@ -45,10 +45,11 @@ private String password; private Features features; private String trustedKeyFile; + private String timeEpsilon; public Response(HttpEntity entity, String username, String password, - Features features, String trustedKeyFile) + Features features, String trustedKeyFile, String timeEpsilon) throws AuthenticationException, IOException { if (entity == null) { @@ -80,6 +81,7 @@ this.password = password; this.features = features; this.trustedKeyFile = trustedKeyFile; + this.timeEpsilon = timeEpsilon; } @Override @@ -97,8 +99,9 @@ public Assertion getAssertion() { if (this.assertion == null && this.root != null) { try { + int timeEps = Integer.parseInt(this.timeEpsilon); TicketValidator validator = - new TicketValidator(this.trustedKeyFile); + new TicketValidator(this.trustedKeyFile, timeEps); this.assertion = validator.checkTicket(this.root); } catch (Exception e) {
--- a/gwt-client/src/main/webapp/WEB-INF/web.xml Tue May 30 12:51:42 2017 +0200 +++ b/gwt-client/src/main/webapp/WEB-INF/web.xml Wed Jun 28 20:09:53 2017 +0200 @@ -51,6 +51,13 @@ </context-param> <context-param> + <!-- Tolerance in milliseconds for validation based on NotBefore and + NotOnOrAfter of the SAML ticket --> + <param-name>saml-time-tolerance</param-name> + <param-value>1000</param-value> + </context-param> + + <context-param> <param-name>features-file</param-name> <param-value>/WEB-INF/features.xml</param-value> </context-param>