Skip to content

Commit 12ae664

Browse files
authored
Fix for exp claim considered valid if equal to now (#652)
exp claim cannot be equal to now
1 parent 6e80ea1 commit 12ae664

File tree

3 files changed

+34
-7
lines changed

3 files changed

+34
-7
lines changed

lib/src/main/java/com/auth0/jwt/JWTVerifier.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ private boolean assertValidInstantClaim(String claimName, Claim claim, long leew
346346
throw new TokenExpiredException(String.format("The Token has expired on %s.", claimVal), claimVal);
347347
}
348348
} else {
349-
isValid = assertInstantIsPast(claimVal, leeway, now);
349+
isValid = assertInstantIsLessThanOrEqualToNow(claimVal, leeway, now);
350350
if (!isValid) {
351351
throw new IncorrectClaimException(
352352
String.format("The Token can't be used before %s.", claimVal), claimName, claim);
@@ -356,10 +356,10 @@ private boolean assertValidInstantClaim(String claimName, Claim claim, long leew
356356
}
357357

358358
private boolean assertInstantIsFuture(Instant claimVal, long leeway, Instant now) {
359-
return !(claimVal != null && now.minus(Duration.ofSeconds(leeway)).isAfter(claimVal));
359+
return claimVal == null || now.minus(Duration.ofSeconds(leeway)).isBefore(claimVal);
360360
}
361361

362-
private boolean assertInstantIsPast(Instant claimVal, long leeway, Instant now) {
362+
private boolean assertInstantIsLessThanOrEqualToNow(Instant claimVal, long leeway, Instant now) {
363363
return !(claimVal != null && now.plus(Duration.ofSeconds(leeway)).isBefore(claimVal));
364364
}
365365

lib/src/test/java/com/auth0/jwt/JWTTest.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.security.interfaces.ECKey;
1313
import java.security.interfaces.RSAKey;
1414
import java.time.Clock;
15+
import java.time.Duration;
1516
import java.time.Instant;
1617
import java.time.ZoneId;
1718
import java.util.Base64;
@@ -270,12 +271,12 @@ public void shouldGetStringAudience() {
270271
@Test
271272
public void shouldGetExpirationTime() {
272273
long seconds = 1477592L;
273-
Clock clock = Clock.fixed(Instant.ofEpochSecond(seconds), ZoneId.of("UTC"));
274+
Clock mockNow = Clock.fixed(Instant.ofEpochSecond(seconds - 1), ZoneId.of("UTC"));
274275

275276
String token = "eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0Nzc1OTJ9.x_ZjkPkKYUV5tdvc0l8go6D_z2kez1MQcOxokXrDc3k";
276277
JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWT.require(Algorithm.HMAC256("secret"));
277278
DecodedJWT jwt = verification
278-
.build(clock)
279+
.build(mockNow)
279280
.verify(token);
280281

281282
assertThat(jwt, is(notNullValue()));

lib/src/test/java/com/auth0/jwt/JWTVerifierTest.java

+28-2
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,7 @@ public void shouldThrowOnNegativeCustomLeeway() {
657657
}
658658

659659
// Expires At
660+
660661
@Test
661662
public void shouldValidateExpiresAtWithLeeway() {
662663
String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0Nzc1OTJ9.isvT0Pqx0yjnZk53mUFSeYFJLDs-Ls9IsNAm86gIdZo";
@@ -674,12 +675,26 @@ public void shouldValidateExpiresAtIfPresent() {
674675
String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0Nzc1OTJ9.isvT0Pqx0yjnZk53mUFSeYFJLDs-Ls9IsNAm86gIdZo";
675676
JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWTVerifier.init(Algorithm.HMAC256("secret"));
676677
DecodedJWT jwt = verification
677-
.build(mockNow)
678+
.build(mockOneSecondEarlier)
678679
.verify(token);
679680

680681
assertThat(jwt, is(notNullValue()));
681682
}
682683

684+
@Test
685+
public void shouldThrowWhenExpiresAtIsNow() {
686+
// exp must be > now
687+
TokenExpiredException e = assertThrows(null, TokenExpiredException.class, () -> {
688+
String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0Nzc1OTJ9.isvT0Pqx0yjnZk53mUFSeYFJLDs-Ls9IsNAm86gIdZo";
689+
JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWTVerifier.init(Algorithm.HMAC256("secret"));
690+
verification
691+
.build(mockNow)
692+
.verify(token);
693+
});
694+
assertThat(e.getMessage(), is("The Token has expired on 1970-01-18T02:26:32Z."));
695+
assertThat(e.getExpiredOn(), is(Instant.ofEpochSecond(1477592L)));
696+
}
697+
683698
@Test
684699
public void shouldThrowOnInvalidExpiresAtIfPresent() {
685700
TokenExpiredException e = assertThrows(null, TokenExpiredException.class, () -> {
@@ -731,7 +746,18 @@ public void shouldThrowOnInvalidNotBeforeIfPresent() {
731746

732747
@Test
733748
public void shouldValidateNotBeforeIfPresent() {
734-
String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0Nzc1OTJ9.isvT0Pqx0yjnZk53mUFSeYFJLDs-Ls9IsNAm86gIdZo";
749+
String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYmYiOjE0Nzc1OTN9.f4zVV0TbbTG5xxDjSoGZ320JIMchGoQCWrnT5MyQdT0";
750+
JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWTVerifier.init(Algorithm.HMAC256("secret"));
751+
DecodedJWT jwt = verification
752+
.build(mockOneSecondLater)
753+
.verify(token);
754+
755+
assertThat(jwt, is(notNullValue()));
756+
}
757+
758+
@Test
759+
public void shouldAcceptNotBeforeEqualToNow() {
760+
String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJuYmYiOjE0Nzc1OTJ9.71XBtRmkAa4iKnyhbS4NPW-Xr26eAVAdHZgmupS7a5o";
735761
JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWTVerifier.init(Algorithm.HMAC256("secret"));
736762
DecodedJWT jwt = verification
737763
.build(mockNow)

0 commit comments

Comments
 (0)