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 <[email protected]>
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);
+    }
 
 }

Reply via email to