From 5fd762e099d61852815bea464c72f59e412c856c Mon Sep 17 00:00:00 2001 From: syed abdul khaliq Date: Tue, 20 Oct 2026 23:15:15 +0530 Subject: [PATCH] fix: return null from asInt/asLong for out-of-range numeric claims asInt() and asLong() only checked isNumber() before narrowing, so a claim such as 4294967419 (2^32 + 123) came back as 123 and satisfied withClaim("name", 123). Use canConvertToInt()/canConvertToLong() so out-of-range values return null, as the Claim javadoc describes. --- .../com/auth0/jwt/impl/JsonNodeClaim.java | 4 ++-- .../java/com/auth0/jwt/JWTVerifierTest.java | 24 +++++++++++++++++++ .../com/auth0/jwt/impl/JsonNodeClaimTest.java | 17 +++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/lib/src/main/java/com/auth0/jwt/impl/JsonNodeClaim.java b/lib/src/main/java/com/auth0/jwt/impl/JsonNodeClaim.java index 481d5955..4173d19e 100644 --- a/lib/src/main/java/com/auth0/jwt/impl/JsonNodeClaim.java +++ b/lib/src/main/java/com/auth0/jwt/impl/JsonNodeClaim.java @@ -37,12 +37,12 @@ public Boolean asBoolean() { @Override public Integer asInt() { - return isMissing() || isNull() || !data.isNumber() ? null : data.asInt(); + return isMissing() || isNull() || !data.canConvertToInt() ? null : data.asInt(); } @Override public Long asLong() { - return isMissing() || isNull() || !data.isNumber() ? null : data.asLong(); + return isMissing() || isNull() || !data.canConvertToLong() ? null : data.asLong(); } @Override diff --git a/lib/src/test/java/com/auth0/jwt/JWTVerifierTest.java b/lib/src/test/java/com/auth0/jwt/JWTVerifierTest.java index 732d6365..64cf20d2 100644 --- a/lib/src/test/java/com/auth0/jwt/JWTVerifierTest.java +++ b/lib/src/test/java/com/auth0/jwt/JWTVerifierTest.java @@ -489,6 +489,30 @@ public void shouldValidateCustomClaimOfTypeLong() { assertThat(jwt, is(notNullValue())); } + @Test + public void shouldThrowOnInvalidCustomClaimValueOfTypeIntegerOutOfRange() { + // {"name": 4294967419} is 2^32 + 123 and must not be narrowed to 123 + String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjo0Mjk0OTY3NDE5fQ.GhKOUxKAss6pfnzjz8RNA_RXl2TuMDbYA9EL6WD5Nxo"; + IncorrectClaimException e = assertThrows(null, IncorrectClaimException.class, () -> + JWTVerifier.init(Algorithm.HMAC256("secret")) + .withClaim("name", 123) + .build() + .verify(token)); + assertThat(e.getClaimName(), is("name")); + } + + @Test + public void shouldThrowOnInvalidCustomClaimValueOfTypeLongOutOfRange() { + // {"name": 18446744073709551739} is 2^64 + 123 and must not be narrowed to 123L + String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoxODQ0Njc0NDA3MzcwOTU1MTczOX0.JlkpbTCD4Po-jQAEJcdYwJLjqNw8uQz8XcEj5OBLgZY"; + IncorrectClaimException e = assertThrows(null, IncorrectClaimException.class, () -> + JWTVerifier.init(Algorithm.HMAC256("secret")) + .withClaim("name", 123L) + .build() + .verify(token)); + assertThat(e.getClaimName(), is("name")); + } + @Test public void shouldValidateCustomClaimOfTypeDouble() { String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoyMy40NX0.7pyX2OmEGaU9q15T8bGFqRm-d3RVTYnqmZNZtxMKSlA"; diff --git a/lib/src/test/java/com/auth0/jwt/impl/JsonNodeClaimTest.java b/lib/src/test/java/com/auth0/jwt/impl/JsonNodeClaimTest.java index 4379cb35..3a3361ad 100644 --- a/lib/src/test/java/com/auth0/jwt/impl/JsonNodeClaimTest.java +++ b/lib/src/test/java/com/auth0/jwt/impl/JsonNodeClaimTest.java @@ -19,6 +19,7 @@ import org.mockito.ArgumentMatchers; import java.io.IOException; +import java.math.BigInteger; import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; @@ -92,6 +93,14 @@ public void shouldGetNullIntIfNotIntValue() { assertThat(claimFromNode(stringValue).asInt(), is(nullValue())); } + @Test + public void shouldGetNullIntIfValueOutOfIntRange() { + JsonNode longValue = mapper.valueToTree(Integer.MAX_VALUE + 124L); + assertThat(claimFromNode(longValue).asInt(), is(nullValue())); + JsonNode bigValue = mapper.valueToTree(BigInteger.ONE.shiftLeft(64).add(BigInteger.valueOf(123))); + assertThat(claimFromNode(bigValue).asInt(), is(nullValue())); + } + @Test public void shouldGetLongValue() { JsonNode value = mapper.valueToTree(Long.MAX_VALUE); @@ -101,6 +110,14 @@ public void shouldGetLongValue() { assertThat(claim.asLong(), is(Long.MAX_VALUE)); } + @Test + public void shouldGetNullLongIfValueOutOfLongRange() { + JsonNode bigValue = mapper.valueToTree(BigInteger.ONE.shiftLeft(64).add(BigInteger.valueOf(123))); + assertThat(claimFromNode(bigValue).asLong(), is(nullValue())); + JsonNode doubleValue = mapper.valueToTree(1e300); + assertThat(claimFromNode(doubleValue).asLong(), is(nullValue())); + } + @Test public void shouldGetNullLongIfNotIntValue() { JsonNode objectValue = mapper.valueToTree(new Object());