diff --git a/src/main/java/io/jsonwebtoken/JwtParser.java b/src/main/java/io/jsonwebtoken/JwtParser.java index 828563ea..44019f77 100644 --- a/src/main/java/io/jsonwebtoken/JwtParser.java +++ b/src/main/java/io/jsonwebtoken/JwtParser.java @@ -28,15 +28,17 @@ public interface JwtParser { public static final char SEPARATOR_CHAR = '.'; /** - * Sets an expected value for the jti claim. + * Ensures that the specified {@code jti} value is present when parsing the JWT. If not present, + * an exception will be thrown indicating that the JWT is invalid and may not be used. * * @param id - * @return the parser for method chaining. + * @return the parser method for chaining. */ JwtParser requireId(String id); /** - * Sets an expected value for the subject claim. + * Ensures that the specified {@code sub} value is present when parsing the JWT. If not present, + * an exception will be thrown indicating that the JWT is invalid and may not be used. * * @param subject * @return the parser for method chaining. @@ -44,7 +46,8 @@ public interface JwtParser { JwtParser requireSubject(String subject); /** - * Sets an expected value for the audience claim. + * Ensures that the specified {@code aud} value is present when parsing the JWT. If not present, + * an exception will be thrown indicating that the JWT is invalid and may not be used. * * @param audience * @return the parser for method chaining. @@ -52,7 +55,8 @@ public interface JwtParser { JwtParser requireAudience(String audience); /** - * Sets an expected value for the issuer claim. + * Ensures that the specified {@code iss} value is present when parsing the JWT. If not present, + * an exception will be thrown indicating that the JWT is invalid and may not be used. * * @param issuer * @return the parser for method chaining. @@ -60,7 +64,8 @@ public interface JwtParser { JwtParser requireIssuer(String issuer); /** - * Sets an expected value for the issuedAt claim. + * Ensures that the specified {@code iat} value is present when parsing the JWT. If not present, + * an exception will be thrown indicating that the JWT is invalid and may not be used. * * @param issuedAt * @return the parser for method chaining. @@ -68,7 +73,8 @@ public interface JwtParser { JwtParser requireIssuedAt(Date issuedAt); /** - * Sets an expected value for the expiration claim. + * Ensures that the specified {@code exp} value is present when parsing the JWT. If not present, + * an exception will be thrown indicating that the JWT is invalid and may not be used. * * @param expiration * @return the parser for method chaining. @@ -76,7 +82,8 @@ public interface JwtParser { JwtParser requireExpiration(Date expiration); /** - * Sets an expected value for the notBefore claim. + * Ensures that the specified {@code nbf} value is present when parsing the JWT. If not present, + * an exception will be thrown indicating that the JWT is invalid and may not be used. * * @param notBefore * @return the parser for method chaining @@ -84,15 +91,14 @@ public interface JwtParser { JwtParser requireNotBefore(Date notBefore); /** - * Sets an expected value for any given claim name. + * Ensures that the specified {@code claimName} value is present when parsing the JWT. If not present, + * an exception will be thrown indicating that the JWT is invalid and may not be used. * - * If an expectation is set for a particular claim name and the JWT being parsed does not have that claim set, + * If a particular claim is required and the JWT being parsed does not have that claim set, * a {@Link MissingClaimException} will be thrown. * - * If an expectation is set for a particular claim name and the JWT being parsed has a value that is different than - * the expected value, a {@link IncorrectClaimException} will be thrown. - * - * If either {@code claimName} is null or empty or {@code value} is null, the expectation is simply ignored. + * If a particular claim is required and the JWT being parsed has a value that is different than + * the required value, a {@link IncorrectClaimException} will be thrown. * * @param claimName * @param value diff --git a/src/main/java/io/jsonwebtoken/impl/DefaultClaims.java b/src/main/java/io/jsonwebtoken/impl/DefaultClaims.java index 38df87ee..196c82ff 100644 --- a/src/main/java/io/jsonwebtoken/impl/DefaultClaims.java +++ b/src/main/java/io/jsonwebtoken/impl/DefaultClaims.java @@ -66,7 +66,7 @@ public class DefaultClaims extends JwtMap implements Claims { @Override public Date getExpiration() { - return getDate(Claims.EXPIRATION); + return get(Claims.EXPIRATION, Date.class); } @Override @@ -77,7 +77,7 @@ public class DefaultClaims extends JwtMap implements Claims { @Override public Date getNotBefore() { - return getDate(Claims.NOT_BEFORE); + return get(Claims.NOT_BEFORE, Date.class); } @Override @@ -88,7 +88,7 @@ public class DefaultClaims extends JwtMap implements Claims { @Override public Date getIssuedAt() { - return getDate(Claims.ISSUED_AT); + return get(Claims.ISSUED_AT, Date.class); } @Override @@ -113,6 +113,13 @@ public class DefaultClaims extends JwtMap implements Claims { Object value = get(claimName); if (value == null) { return null; } + if (Claims.EXPIRATION.equals(claimName) || + Claims.ISSUED_AT.equals(claimName) || + Claims.NOT_BEFORE.equals(claimName) + ) { + value = getDate(claimName); + } + if (requiredType == Date.class && value instanceof Long) { value = new Date((Long)value); } diff --git a/src/main/java/io/jsonwebtoken/impl/DefaultJwtParser.java b/src/main/java/io/jsonwebtoken/impl/DefaultJwtParser.java index 9bbe3b2b..a759549d 100644 --- a/src/main/java/io/jsonwebtoken/impl/DefaultJwtParser.java +++ b/src/main/java/io/jsonwebtoken/impl/DefaultJwtParser.java @@ -381,16 +381,18 @@ public class DefaultJwtParser implements JwtParser { Object expectedClaimValue = expectedClaims.get(expectedClaimName); Object actualClaimValue = claims.get(expectedClaimName); - if (Claims.ISSUED_AT.equals(expectedClaimName)) { - expectedClaimValue = expectedClaims.getIssuedAt(); - actualClaimValue = claims.getIssuedAt(); - } else if (Claims.EXPIRATION.equals(expectedClaimName)) { - expectedClaimValue = expectedClaims.getExpiration(); - actualClaimValue = claims.getExpiration(); - } else if (Claims.NOT_BEFORE.equals(expectedClaimName)) { - expectedClaimValue = expectedClaims.getNotBefore(); - actualClaimValue = claims.getNotBefore(); - } else if (expectedClaimValue instanceof Date && actualClaimValue != null && actualClaimValue instanceof Long) { + if ( + Claims.ISSUED_AT.equals(expectedClaimName) || + Claims.EXPIRATION.equals(expectedClaimName) || + Claims.NOT_BEFORE.equals(expectedClaimName) + ) { + expectedClaimValue = expectedClaims.get(expectedClaimName, Date.class); + actualClaimValue = claims.get(expectedClaimName, Date.class); + } else if ( + expectedClaimValue instanceof Date && + actualClaimValue != null && + actualClaimValue instanceof Long + ) { actualClaimValue = new Date((Long)actualClaimValue); } diff --git a/src/test/groovy/io/jsonwebtoken/impl/DefaultClaimsTest.groovy b/src/test/groovy/io/jsonwebtoken/impl/DefaultClaimsTest.groovy index cb584a4d..161957f0 100644 --- a/src/test/groovy/io/jsonwebtoken/impl/DefaultClaimsTest.groovy +++ b/src/test/groovy/io/jsonwebtoken/impl/DefaultClaimsTest.groovy @@ -64,7 +64,7 @@ class DefaultClaimsTest { def actual = new Date(); claims.put("aDate", actual) Date expected = claims.get("aDate", Date.class); - assertEquals(expected, actual); + assertEquals(expected, actual) } @Test @@ -73,6 +73,31 @@ class DefaultClaimsTest { // note that Long is stored in claim claims.put("aDate", actual.getTime()) Date expected = claims.get("aDate", Date.class); - assertEquals(expected, actual); + assertEquals(expected, actual) } + + @Test + void testGetClaimExpiration_Success() { + def now = new Date(System.currentTimeMillis()) + claims.setExpiration(now) + Date expected = claims.get("exp", Date.class) + assertEquals(expected, claims.getExpiration()) + } + + @Test + void testGetClaimIssuedAt_Success() { + def now = new Date(System.currentTimeMillis()) + claims.setIssuedAt(now) + Date expected = claims.get("iat", Date.class) + assertEquals(expected, claims.getIssuedAt()) + } + + @Test + void testGetClaimNotBefore_Success() { + def now = new Date(System.currentTimeMillis()) + claims.setNotBefore(now) + Date expected = claims.get("nbf", Date.class) + assertEquals(expected, claims.getNotBefore()) + } + }