[java-oidc-common] branch main updated: JCOMOIDC-20 - Add clockskew to authentication time check

Phil Smart philip.smart at jisc.ac.uk
Wed May 19 15:59:41 UTC 2021


This is an automated email from the git hooks/post-receive script.

philsmart pushed a commit to branch main
in repository java-oidc-common.

View the commit online:
http://git.shibboleth.net/view/?p=java-oidc-common.git;a=commit;h=6ed260792cb01a3c07012e8a41d378bdc43462f0

The following commit(s) were added to refs/heads/main by this push:
       new  6ed2607   JCOMOIDC-20 - Add clockskew to authentication time check
6ed2607 is described below

commit 6ed260792cb01a3c07012e8a41d378bdc43462f0
Author: Phil Smart <philip.smart at jisc.ac.uk>
AuthorDate: Wed May 19 16:59:39 2021 +0100

    JCOMOIDC-20 - Add clockskew to authentication time check
    
     - Clockskew property added and used as part of calculations to
    determine if the authentication was in the future.
    
    https://issues.shibboleth.net/jira/browse/JCOMOIDC-20
---
 .../impl/AuthenticationTimeClaimsValidator.java    | 31 +++++++++++++++++-----
 .../jwt/claims/impl/ExpiryClaimsValidator.java     |  2 +-
 .../AuthenticationTimeClaimsValidatorTest.java     | 18 +++++++++++++
 3 files changed, 44 insertions(+), 7 deletions(-)

diff --git a/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/jwt/claims/impl/AuthenticationTimeClaimsValidator.java b/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/jwt/claims/impl/AuthenticationTimeClaimsValidator.java
index 4e540c5..d429952 100644
--- a/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/jwt/claims/impl/AuthenticationTimeClaimsValidator.java
+++ b/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/jwt/claims/impl/AuthenticationTimeClaimsValidator.java
@@ -41,8 +41,8 @@ import net.shibboleth.utilities.java.support.logic.Constraint;
 
 /**
  * Verifies the auth_time (when the End-User authentication took place) is within a valid expiration window.
- * <p>Uses a predicate to determine if the auth_time was request e.g. was explicitly requested, or the max_age
- * claim was requested. Defaults to true.</p>
+ * <p>A predicate determines if the auth_time was requested e.g. was explicitly requested, or the max_age
+ * claim was set. Defaults to true.</p>
  */
 @ThreadSafeAfterInit
 public class AuthenticationTimeClaimsValidator extends AbstractClaimsValidator {
@@ -51,11 +51,17 @@ public class AuthenticationTimeClaimsValidator extends AbstractClaimsValidator {
     @Nonnull private final Logger log = LoggerFactory.getLogger(AuthenticationTimeClaimsValidator.class);
     
     /** 
-     * If request, the amount of time for which a token is valid 
-     * after if it was issued. (Default value: 60 seconds) 
+     * If requested, the amount of time for which a token is valid 
+     * after if it was first issued. (Default value: 60 seconds) 
      */
     @Nonnull private Duration authnLifetime;
     
+    /** 
+     * Positive clock skew adjustment to consider when checking auth_time is not in the future 
+     * or has expired. (Default value: 60 seconds). 
+     */
+    @Nonnull private Duration clockSkew;
+    
     /**
      *  Has the auth_time been requested, either explicitly or from the max_age parameter?
      *  Defaults to true. 
@@ -65,8 +71,20 @@ public class AuthenticationTimeClaimsValidator extends AbstractClaimsValidator {
     /** Constructor.*/
     public AuthenticationTimeClaimsValidator() {
         authnLifetime = Duration.ofSeconds(60);
+        clockSkew = Duration.ofSeconds(60);
         requested = Predicates.alwaysTrue();
     }
+    
+    /**
+     * Set the clock skew.
+     * 
+     * @param skew clock skew to set
+     */
+    public void setClockSkew(@Nonnull final Duration skew) {  
+        ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+        
+        clockSkew = Constraint.isNotNull(skew, "Clock skew cannot be null");
+    }
 
     
     /**
@@ -110,10 +128,11 @@ public class AuthenticationTimeClaimsValidator extends AbstractClaimsValidator {
                 }
                 final Instant authTime = authTimeDate.toInstant();
                 final Instant now = Instant.now();
-                final Instant expiration = authTime.plus(authnLifetime);
+                final Instant latestValid = now.plus(clockSkew);
+                final Instant expiration = authTime.plus(clockSkew).plus(authnLifetime);
                 
                 // Check time of authentication wasn't in the future
-                if (authTime.isAfter(now)) {
+                if (authTime.isAfter(latestValid)) {
                     log.warn("Authentication is not yet valid: auth_time was {}, latest valid is: {}",
                             authTime, now);
                     throw new JWTValidationException("JWT token authentication time is not yet valid");
diff --git a/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/jwt/claims/impl/ExpiryClaimsValidator.java b/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/jwt/claims/impl/ExpiryClaimsValidator.java
index 0315893..d6db88e 100644
--- a/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/jwt/claims/impl/ExpiryClaimsValidator.java
+++ b/oidc-common-crypto-impl/src/main/java/net/shibboleth/oidc/security/jwt/claims/impl/ExpiryClaimsValidator.java
@@ -43,7 +43,7 @@ import net.shibboleth.utilities.java.support.logic.Constraint;
 public class ExpiryClaimsValidator extends AbstractClaimsValidator {
     
     /** 
-     * Positive clock skew adjustment to consider when checking JWT not before and expiration 
+     * Positive clock skew adjustment to consider when checking JWT expiration 
      * (Default value: 60 seconds). 
      */
     @Nonnull private Duration clockSkew;
diff --git a/oidc-common-crypto-impl/src/test/java/net/shibboleth/oidc/security/jwt/claims/impl/AuthenticationTimeClaimsValidatorTest.java b/oidc-common-crypto-impl/src/test/java/net/shibboleth/oidc/security/jwt/claims/impl/AuthenticationTimeClaimsValidatorTest.java
index 036f3fc..e93f38e 100644
--- a/oidc-common-crypto-impl/src/test/java/net/shibboleth/oidc/security/jwt/claims/impl/AuthenticationTimeClaimsValidatorTest.java
+++ b/oidc-common-crypto-impl/src/test/java/net/shibboleth/oidc/security/jwt/claims/impl/AuthenticationTimeClaimsValidatorTest.java
@@ -50,6 +50,7 @@ public class AuthenticationTimeClaimsValidatorTest extends AbstractClaimsValidat
                 IDTokenClaims.AUTHENTICATION_TIME.getClaimName(), Instant.now().getEpochSecond()).build();
         validator.setId("test-validator");   
         validator.setAuthnLifetime(Duration.ofMinutes(1));
+        validator.setClockSkew(Duration.ofSeconds(0));
         validator.initialize();
         validator.validate(claimsSet, prc);   }
     
@@ -62,6 +63,7 @@ public class AuthenticationTimeClaimsValidatorTest extends AbstractClaimsValidat
                 Instant.now().minus(Duration.ofSeconds(30)).getEpochSecond()).build();
         validator.setId("test-validator");   
         validator.setAuthnLifetime(Duration.ofMinutes(1));
+        validator.setClockSkew(Duration.ofSeconds(0));
         validator.initialize();
         validator.validate(claimsSet, prc);
     }
@@ -93,6 +95,7 @@ public class AuthenticationTimeClaimsValidatorTest extends AbstractClaimsValidat
                 Instant.now().minus(Duration.ofMinutes(10)).getEpochSecond()).build();
         validator.setId("test-validator");   
         validator.setAuthnLifetime(Duration.ofMinutes(1));
+        validator.setClockSkew(Duration.ofMinutes(0));
         validator.initialize();
         validator.validate(claimsSet, prc);
     }
@@ -104,6 +107,21 @@ public class AuthenticationTimeClaimsValidatorTest extends AbstractClaimsValidat
                 Instant.now().plus(Duration.ofSeconds(30)).getEpochSecond()).build();
         validator.setId("test-validator");   
         validator.setAuthnLifetime(Duration.ofMinutes(1));
+        //set clockskew to 10 seconds, and JWT is 30 seconds in the future, so should throw
+        validator.setClockSkew(Duration.ofSeconds(10));
+        validator.initialize();
+        validator.validate(claimsSet, prc);
+    }
+    
+    @Test
+    public void doInValidateInTheFutureButInsideSkew() throws JWTValidationException, ComponentInitializationException {
+        final JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().claim(
+                IDTokenClaims.AUTHENTICATION_TIME.getClaimName(), 
+                Instant.now().plus(Duration.ofSeconds(30)).getEpochSecond()).build();
+        validator.setId("test-validator");   
+        validator.setAuthnLifetime(Duration.ofMinutes(1));
+        //set clockskew to 60 seconds, and JWT is 30 seconds in the future, so should be fine
+        validator.setClockSkew(Duration.ofSeconds(60));
         validator.initialize();
         validator.validate(claimsSet, prc);
     }

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list