You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2026/08/31 13:59:22 UTC

(cxf) branch coheigea/jwt-ttl created (now 70655008050)

This is an automated email from the ASF dual-hosted git repository.

coheigea pushed a change to branch coheigea/jwt-ttl
in repository https://gitbox.apache.org/repos/asf/cxf.git


      at 70655008050 Enforce a default TTL in AbstractJwtAuthenticationFilter so that tokens that don't have exp will be checked for expiration by default

This branch includes the following new commits:

     new 70655008050 Enforce a default TTL in AbstractJwtAuthenticationFilter so that tokens that don't have exp will be checked for expiration by default

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(cxf) 01/01: Enforce a default TTL in AbstractJwtAuthenticationFilter so that tokens that don't have exp will be checked for expiration by default

Posted by co...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

coheigea pushed a commit to branch coheigea/jwt-ttl
in repository https://gitbox.apache.org/repos/asf/cxf.git

commit 706550080500576ff6bb2a9fdc9cf430e303ae5e
Author: Colm O hEigeartaigh <co...@apache.org>
AuthorDate: Mon Aug 31 14:58:26 2026 +0100

    Enforce a default TTL in AbstractJwtAuthenticationFilter so that tokens that don't have exp will be checked for expiration by default
---
 .../jaxrs/AbstractJwtAuthenticationFilter.java     |  5 +++
 .../apache/cxf/rs/security/jose/jwt/JwtUtils.java  |  4 +--
 .../cxf/rs/security/jose/jwt/JwtUtilsTest.java     | 36 ++++++++++++++++++++++
 3 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwtAuthenticationFilter.java b/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwtAuthenticationFilter.java
index 673addd4d3f..7c99b7fd530 100644
--- a/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwtAuthenticationFilter.java
+++ b/rt/rs/security/jose-parent/jose-jaxrs/src/main/java/org/apache/cxf/rs/security/jose/jaxrs/AbstractJwtAuthenticationFilter.java
@@ -41,10 +41,15 @@ import org.apache.cxf.security.SecurityContext;
 @Priority(Priorities.AUTHENTICATION)
 public abstract class AbstractJwtAuthenticationFilter extends JoseJwtConsumer implements ContainerRequestFilter {
     protected static final Logger LOG = LogUtils.getL7dLogger(AbstractJwtAuthenticationFilter.class);
+    private static final int DEFAULT_TTL_SECS = 300;
 
     private String roleClaim;
     private boolean validateAudience = true;
 
+    protected AbstractJwtAuthenticationFilter() {
+        setTtl(DEFAULT_TTL_SECS);
+    }
+
     @Override
     public void filter(ContainerRequestContext requestContext) throws IOException {
         String encodedJwtToken = getEncodedJwtToken(requestContext);
diff --git a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtUtils.java b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtUtils.java
index 10b08220a93..6c47611e8ab 100644
--- a/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtUtils.java
+++ b/rt/rs/security/jose-parent/jose/src/main/java/org/apache/cxf/rs/security/jose/jwt/JwtUtils.java
@@ -157,8 +157,8 @@ public final class JwtUtils {
 
     public static void validateTokenClaims(JwtClaims claims, int timeToLive, int clockOffset,
                                            boolean validateAudienceRestriction) {
-        // If we have no issued time then we need to have an expiry
-        boolean expiredRequired = claims.getIssuedAt() == null;
+        // A positive TTL bounds the token age from its issued time.
+        boolean expiredRequired = claims.getIssuedAt() == null || timeToLive <= 0;
         validateJwtExpiry(claims, clockOffset, expiredRequired);
 
         validateJwtNotBefore(claims, clockOffset, false);
diff --git a/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jwt/JwtUtilsTest.java b/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jwt/JwtUtilsTest.java
index af58d2d0e7c..dd8e5aa5392 100644
--- a/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jwt/JwtUtilsTest.java
+++ b/rt/rs/security/jose-parent/jose/src/test/java/org/apache/cxf/rs/security/jose/jwt/JwtUtilsTest.java
@@ -213,5 +213,41 @@ public class JwtUtilsTest {
         }
     }
 
+    @org.junit.Test
+    public void testIssuedAtOnlyTokenRejectedWithoutTTL() {
+        JwtClaims claims = new JwtClaims();
+        claims.setSubject("alice");
+        claims.setIssuer("DoubleItSTSIssuer");
+        claims.setIssuedAt(ZonedDateTime.now(ZoneOffset.UTC).toEpochSecond());
+
+        try {
+            JwtUtils.validateTokenClaims(claims, 0, 0, false);
+            fail("Failure expected on an iat-only token with no configured TTL");
+        } catch (JwtException ex) {
+            // expected
+        }
+    }
+
+    @org.junit.Test
+    public void testIssuedAtOnlyTokenAcceptedWithTTL() {
+        JwtClaims claims = new JwtClaims();
+        claims.setSubject("alice");
+        claims.setIssuer("DoubleItSTSIssuer");
+        claims.setIssuedAt(ZonedDateTime.now(ZoneOffset.UTC).toEpochSecond());
+
+        JwtUtils.validateTokenClaims(claims, 60, 0, false);
+    }
+
+    @org.junit.Test
+    public void testExpiryTokenAcceptedWithoutTTL() {
+        JwtClaims claims = new JwtClaims();
+        claims.setSubject("alice");
+        claims.setIssuer("DoubleItSTSIssuer");
+        ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
+        claims.setIssuedAt(now.toEpochSecond());
+        claims.setExpiryTime(now.plusMinutes(5L).toEpochSecond());
+
+        JwtUtils.validateTokenClaims(claims, 0, 0, false);
+    }
 
 }