package com.auth0.jwt; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.AlgorithmMismatchException; import com.auth0.jwt.exceptions.InvalidClaimException; import com.auth0.jwt.exceptions.TokenExpiredException; import com.auth0.jwt.interfaces.Clock; import com.auth0.jwt.interfaces.DecodedJWT; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import java.util.Date; import java.util.HashMap; import java.util.Map; import static org.hamcrest.Matchers.*; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class JWTVerifierTest { private static final long DATE_TOKEN_MS_VALUE = 1477592 * 1000; @Rule public ExpectedException exception = ExpectedException.none(); @Test public void shouldThrowWhenInitializedWithoutAlgorithm() throws Exception { exception.expect(IllegalArgumentException.class); exception.expectMessage("The Algorithm cannot be null"); JWTVerifier.init(null); } @Test public void shouldThrowWhenAlgorithmDoesntMatchTheTokensAlgorithm() throws Exception { exception.expect(AlgorithmMismatchException.class); exception.expectMessage("The provided Algorithm doesn't match the one defined in the JWT's Header."); JWTVerifier verifier = JWTVerifier.init(Algorithm.HMAC512("secret")).build(); verifier.verify("eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJhdXRoMCJ9.s69x7Mmu4JqwmdxiK6sesALO7tcedbFsKEEITUxw9ho"); } @Test public void shouldValidateIssuer() throws Exception { String token = "eyJhbGciOiJIUzI1NiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mZ0m_N1J4PgeqWmi903JuUoDRZDBPB7HwkS4nVyWH1M"; DecodedJWT jwt = JWTVerifier.init(Algorithm.HMAC256("secret")) .withIssuer("auth0") .build() .verify(token); assertThat(jwt, is(notNullValue())); } @Test public void shouldThrowOnInvalidIssuer() throws Exception { exception.expect(InvalidClaimException.class); exception.expectMessage("The Claim 'iss' value doesn't match the required one."); String token = "eyJhbGciOiJIUzI1NiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mZ0m_N1J4PgeqWmi903JuUoDRZDBPB7HwkS4nVyWH1M"; JWTVerifier.init(Algorithm.HMAC256("secret")) .withIssuer("invalid") .build() .verify(token); } @Test public void shouldValidateSubject() throws Exception { String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.Rq8IxqeX7eA6GgYxlcHdPFVRNFFZc5rEI3MQTZZbK3I"; DecodedJWT jwt = JWTVerifier.init(Algorithm.HMAC256("secret")) .withSubject("1234567890") .build() .verify(token); assertThat(jwt, is(notNullValue())); } @Test public void shouldThrowOnInvalidSubject() throws Exception { exception.expect(InvalidClaimException.class); exception.expectMessage("The Claim 'sub' value doesn't match the required one."); String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.Rq8IxqeX7eA6GgYxlcHdPFVRNFFZc5rEI3MQTZZbK3I"; JWTVerifier.init(Algorithm.HMAC256("secret")) .withSubject("invalid") .build() .verify(token); } @Test public void shouldValidateAudience() throws Exception { String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJNYXJrIn0.xWB6czYI0XObbVhLAxe55TwChWZg7zO08RxONWU2iY4"; DecodedJWT jwt = JWTVerifier.init(Algorithm.HMAC256("secret")) .withAudience("Mark") .build() .verify(token); assertThat(jwt, is(notNullValue())); String tokenArr = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiTWFyayIsIkRhdmlkIl19.6WfbIt8m61f9WlCYIQn5CThvw4UNyC66qrPaoinfssw"; DecodedJWT jwtArr = JWTVerifier.init(Algorithm.HMAC256("secret")) .withAudience("Mark", "David") .build() .verify(tokenArr); assertThat(jwtArr, is(notNullValue())); } @Test public void shouldAcceptPartialAudience() throws Exception { //Token 'aud' = ["Mark", "David", "John"] String tokenArr = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiTWFyayIsIkRhdmlkIiwiSm9obiJdfQ.DX5xXiCaYvr54x_iL0LZsJhK7O6HhAdHeDYkgDeb0Rw"; DecodedJWT jwtArr = JWTVerifier.init(Algorithm.HMAC256("secret")) .withAudience("John") .build() .verify(tokenArr); assertThat(jwtArr, is(notNullValue())); } @Test public void shouldThrowOnInvalidAudience() throws Exception { exception.expect(InvalidClaimException.class); exception.expectMessage("The Claim 'aud' value doesn't contain the required audience."); String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.Rq8IxqeX7eA6GgYxlcHdPFVRNFFZc5rEI3MQTZZbK3I"; JWTVerifier.init(Algorithm.HMAC256("secret")) .withAudience("nope") .build() .verify(token); } @Test public void shouldThrowOnNullCustomClaimName() throws Exception { exception.expect(IllegalArgumentException.class); exception.expectMessage("The Custom Claim's name can't be null."); JWTVerifier.init(Algorithm.HMAC256("secret")) .withClaim(null, "value"); } @Test public void shouldThrowOnInvalidCustomClaimValueOfTypeString() throws Exception { exception.expect(InvalidClaimException.class); exception.expectMessage("The Claim 'name' value doesn't match the required one."); String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjpbInNvbWV0aGluZyJdfQ.3ENLez6tU_fG0SVFrGmISltZPiXLSHaz_dyn-XFTEGQ"; JWTVerifier.init(Algorithm.HMAC256("secret")) .withClaim("name", "value") .build() .verify(token); } @Test public void shouldThrowOnInvalidCustomClaimValueOfTypeInteger() throws Exception { exception.expect(InvalidClaimException.class); exception.expectMessage("The Claim 'name' value doesn't match the required one."); String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjpbInNvbWV0aGluZyJdfQ.3ENLez6tU_fG0SVFrGmISltZPiXLSHaz_dyn-XFTEGQ"; JWTVerifier.init(Algorithm.HMAC256("secret")) .withClaim("name", 123) .build() .verify(token); } @Test public void shouldThrowOnInvalidCustomClaimValueOfTypeDouble() throws Exception { exception.expect(InvalidClaimException.class); exception.expectMessage("The Claim 'name' value doesn't match the required one."); String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjpbInNvbWV0aGluZyJdfQ.3ENLez6tU_fG0SVFrGmISltZPiXLSHaz_dyn-XFTEGQ"; JWTVerifier.init(Algorithm.HMAC256("secret")) .withClaim("name", 23.45) .build() .verify(token); } @Test public void shouldThrowOnInvalidCustomClaimValueOfTypeBoolean() throws Exception { exception.expect(InvalidClaimException.class); exception.expectMessage("The Claim 'name' value doesn't match the required one."); String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjpbInNvbWV0aGluZyJdfQ.3ENLez6tU_fG0SVFrGmISltZPiXLSHaz_dyn-XFTEGQ"; JWTVerifier.init(Algorithm.HMAC256("secret")) .withClaim("name", true) .build() .verify(token); } @Test public void shouldThrowOnInvalidCustomClaimValueOfTypeDate() throws Exception { exception.expect(InvalidClaimException.class); exception.expectMessage("The Claim 'name' value doesn't match the required one."); String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjpbInNvbWV0aGluZyJdfQ.3ENLez6tU_fG0SVFrGmISltZPiXLSHaz_dyn-XFTEGQ"; JWTVerifier.init(Algorithm.HMAC256("secret")) .withClaim("name", new Date()) .build() .verify(token); } @Test public void shouldThrowOnInvalidCustomClaimValue() throws Exception { exception.expect(InvalidClaimException.class); exception.expectMessage("The Claim 'name' value doesn't match the required one."); String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjpbInNvbWV0aGluZyJdfQ.3ENLez6tU_fG0SVFrGmISltZPiXLSHaz_dyn-XFTEGQ"; Map<String, Object> map = new HashMap<>(); map.put("name", new Object()); JWTVerifier verifier = new JWTVerifier(Algorithm.HMAC256("secret"), map, new ClockImpl()); verifier.verify(token); } @Test public void shouldValidateCustomClaimOfTypeString() throws Exception { String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoidmFsdWUifQ.Jki8pvw6KGbxpMinufrgo6RDL1cu7AtNMJYVh6t-_cE"; DecodedJWT jwt = JWTVerifier.init(Algorithm.HMAC256("secret")) .withClaim("name", "value") .build() .verify(token); assertThat(jwt, is(notNullValue())); } @Test public void shouldValidateCustomClaimOfTypeInteger() throws Exception { String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoxMjN9.XZAudnA7h3_Al5kJydzLjw6RzZC3Q6OvnLEYlhNW7HA"; DecodedJWT jwt = JWTVerifier.init(Algorithm.HMAC256("secret")) .withClaim("name", 123) .build() .verify(token); assertThat(jwt, is(notNullValue())); } @Test public void shouldValidateCustomClaimOfTypeLong() throws Exception { String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjo5MjIzMzcyMDM2ODU0Nzc2MDB9.km-IwQ5IDnTZFmuJzhSgvjTzGkn_Z5X29g4nAuVC56I"; DecodedJWT jwt = JWTVerifier.init(Algorithm.HMAC256("secret")) .withClaim("name", 922337203685477600L) .build() .verify(token); assertThat(jwt, is(notNullValue())); } @Test public void shouldValidateCustomClaimOfTypeDouble() throws Exception { String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoyMy40NX0.7pyX2OmEGaU9q15T8bGFqRm-d3RVTYnqmZNZtxMKSlA"; DecodedJWT jwt = JWTVerifier.init(Algorithm.HMAC256("secret")) .withClaim("name", 23.45) .build() .verify(token); assertThat(jwt, is(notNullValue())); } @Test public void shouldValidateCustomClaimOfTypeBoolean() throws Exception { String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjp0cnVlfQ.FwQ8VfsZNRqBa9PXMinSIQplfLU4-rkCLfIlTLg_MV0"; DecodedJWT jwt = JWTVerifier.init(Algorithm.HMAC256("secret")) .withClaim("name", true) .build() .verify(token); assertThat(jwt, is(notNullValue())); } @Test public void shouldValidateCustomClaimOfTypeDate() throws Exception { String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoxNDc4ODkxNTIxfQ.mhioumeok8fghQEhTKF3QtQAksSvZ_9wIhJmgZLhJ6c"; Date date = new Date(1478891521000L); DecodedJWT jwt = JWTVerifier.init(Algorithm.HMAC256("secret")) .withClaim("name", date) .build() .verify(token); assertThat(jwt, is(notNullValue())); } @Test public void shouldValidateCustomArrayClaimOfTypeString() throws Exception { String token = "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjpbInRleHQiLCIxMjMiLCJ0cnVlIl19.lxM8EcmK1uSZRAPd0HUhXGZJdauRmZmLjoeqz4J9yAA"; DecodedJWT jwt = JWTVerifier.init(Algorithm.HMAC256("secret")) .withArrayClaim("name", "text", "123", "true") .build() .verify(token); assertThat(jwt, is(notNullValue())); } @Test public void shouldValidateCustomArrayClaimOfTypeInteger() throws Exception { String token = "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjpbMSwyLDNdfQ.UEuMKRQYrzKAiPpPLhIVawWkKWA1zj0_GderrWUIyFE"; DecodedJWT jwt = JWTVerifier.init(Algorithm.HMAC256("secret")) .withArrayClaim("name", 1, 2, 3) .build() .verify(token); assertThat(jwt, is(notNullValue())); } // Generic Delta @SuppressWarnings("RedundantCast") @Test public void shouldAddDefaultLeewayToDateClaims() throws Exception { Algorithm algorithm = mock(Algorithm.class); JWTVerifier verifier = JWTVerifier.init(algorithm) .build(); assertThat(verifier.claims, is(notNullValue())); assertThat(verifier.claims, hasEntry("iat", (Object) 0L)); assertThat(verifier.claims, hasEntry("exp", (Object) 0L)); assertThat(verifier.claims, hasEntry("nbf", (Object) 0L)); } @SuppressWarnings("RedundantCast") @Test public void shouldAddCustomLeewayToDateClaims() throws Exception { Algorithm algorithm = mock(Algorithm.class); JWTVerifier verifier = JWTVerifier.init(algorithm) .acceptLeeway(1234L) .build(); assertThat(verifier.claims, is(notNullValue())); assertThat(verifier.claims, hasEntry("iat", (Object) 1234L)); assertThat(verifier.claims, hasEntry("exp", (Object) 1234L)); assertThat(verifier.claims, hasEntry("nbf", (Object) 1234L)); } @SuppressWarnings("RedundantCast") @Test public void shouldOverrideDefaultIssuedAtLeeway() throws Exception { Algorithm algorithm = mock(Algorithm.class); JWTVerifier verifier = JWTVerifier.init(algorithm) .acceptLeeway(1234L) .acceptIssuedAt(9999L) .build(); assertThat(verifier.claims, is(notNullValue())); assertThat(verifier.claims, hasEntry("iat", (Object) 9999L)); assertThat(verifier.claims, hasEntry("exp", (Object) 1234L)); assertThat(verifier.claims, hasEntry("nbf", (Object) 1234L)); } @SuppressWarnings("RedundantCast") @Test public void shouldOverrideDefaultExpiresAtLeeway() throws Exception { Algorithm algorithm = mock(Algorithm.class); JWTVerifier verifier = JWTVerifier.init(algorithm) .acceptLeeway(1234L) .acceptExpiresAt(9999L) .build(); assertThat(verifier.claims, is(notNullValue())); assertThat(verifier.claims, hasEntry("iat", (Object) 1234L)); assertThat(verifier.claims, hasEntry("exp", (Object) 9999L)); assertThat(verifier.claims, hasEntry("nbf", (Object) 1234L)); } @SuppressWarnings("RedundantCast") @Test public void shouldOverrideDefaultNotBeforeLeeway() throws Exception { Algorithm algorithm = mock(Algorithm.class); JWTVerifier verifier = JWTVerifier.init(algorithm) .acceptLeeway(1234L) .acceptNotBefore(9999L) .build(); assertThat(verifier.claims, is(notNullValue())); assertThat(verifier.claims, hasEntry("iat", (Object) 1234L)); assertThat(verifier.claims, hasEntry("exp", (Object) 1234L)); assertThat(verifier.claims, hasEntry("nbf", (Object) 9999L)); } @Test public void shouldThrowOnNegativeCustomLeeway() throws Exception { exception.expect(IllegalArgumentException.class); exception.expectMessage("Leeway value can't be negative."); Algorithm algorithm = mock(Algorithm.class); JWTVerifier.init(algorithm) .acceptLeeway(-1); } // Expires At @Test public void shouldValidateExpiresAtWithLeeway() throws Exception { Clock clock = mock(Clock.class); when(clock.getToday()).thenReturn(new Date(DATE_TOKEN_MS_VALUE + 1000)); String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0Nzc1OTJ9.isvT0Pqx0yjnZk53mUFSeYFJLDs-Ls9IsNAm86gIdZo"; JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWTVerifier.init(Algorithm.HMAC256("secret")) .acceptExpiresAt(2); DecodedJWT jwt = verification .build(clock) .verify(token); assertThat(jwt, is(notNullValue())); } @Test public void shouldValidateExpiresAtIfPresent() throws Exception { Clock clock = mock(Clock.class); when(clock.getToday()).thenReturn(new Date(DATE_TOKEN_MS_VALUE)); String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0Nzc1OTJ9.isvT0Pqx0yjnZk53mUFSeYFJLDs-Ls9IsNAm86gIdZo"; JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWTVerifier.init(Algorithm.HMAC256("secret")); DecodedJWT jwt = verification .build(clock) .verify(token); assertThat(jwt, is(notNullValue())); } @Test public void shouldThrowOnInvalidExpiresAtIfPresent() throws Exception { exception.expect(TokenExpiredException.class); exception.expectMessage(startsWith("The Token has expired on")); Clock clock = mock(Clock.class); when(clock.getToday()).thenReturn(new Date(DATE_TOKEN_MS_VALUE + 1000)); String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0Nzc1OTJ9.isvT0Pqx0yjnZk53mUFSeYFJLDs-Ls9IsNAm86gIdZo"; JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWTVerifier.init(Algorithm.HMAC256("secret")); verification .build(clock) .verify(token); } @Test public void shouldThrowOnNegativeExpiresAtLeeway() throws Exception { exception.expect(IllegalArgumentException.class); exception.expectMessage("Leeway value can't be negative."); Algorithm algorithm = mock(Algorithm.class); JWTVerifier.init(algorithm) .acceptExpiresAt(-1); } // Not before @Test public void shouldValidateNotBeforeWithLeeway() throws Exception { Clock clock = mock(Clock.class); when(clock.getToday()).thenReturn(new Date(DATE_TOKEN_MS_VALUE - 1000)); String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0Nzc1OTJ9.wq4ZmnSF2VOxcQBxPLfeh1J2Ozy1Tj5iUaERm3FKaw8"; JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWTVerifier.init(Algorithm.HMAC256("secret")) .acceptNotBefore(2); DecodedJWT jwt = verification .build(clock) .verify(token); assertThat(jwt, is(notNullValue())); } @Test public void shouldThrowOnInvalidNotBeforeIfPresent() throws Exception { exception.expect(InvalidClaimException.class); exception.expectMessage(startsWith("The Token can't be used before")); Clock clock = mock(Clock.class); when(clock.getToday()).thenReturn(new Date(DATE_TOKEN_MS_VALUE - 1000)); String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0Nzc1OTJ9.wq4ZmnSF2VOxcQBxPLfeh1J2Ozy1Tj5iUaERm3FKaw8"; JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWTVerifier.init(Algorithm.HMAC256("secret")); verification .build(clock) .verify(token); } @Test public void shouldValidateNotBeforeIfPresent() throws Exception { Clock clock = mock(Clock.class); when(clock.getToday()).thenReturn(new Date(DATE_TOKEN_MS_VALUE)); String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0Nzc1OTJ9.isvT0Pqx0yjnZk53mUFSeYFJLDs-Ls9IsNAm86gIdZo"; JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWTVerifier.init(Algorithm.HMAC256("secret")); DecodedJWT jwt = verification .build(clock) .verify(token); assertThat(jwt, is(notNullValue())); } @Test public void shouldThrowOnNegativeNotBeforeLeeway() throws Exception { exception.expect(IllegalArgumentException.class); exception.expectMessage("Leeway value can't be negative."); Algorithm algorithm = mock(Algorithm.class); JWTVerifier.init(algorithm) .acceptNotBefore(-1); } // Issued At @Test public void shouldValidateIssuedAtWithLeeway() throws Exception { Clock clock = mock(Clock.class); when(clock.getToday()).thenReturn(new Date(DATE_TOKEN_MS_VALUE - 1000)); String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0Nzc1OTJ9.0WJky9eLN7kuxLyZlmbcXRL3Wy8hLoNCEk5CCl2M4lo"; JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWTVerifier.init(Algorithm.HMAC256("secret")) .acceptIssuedAt(2); DecodedJWT jwt = verification .build(clock) .verify(token); assertThat(jwt, is(notNullValue())); } @Test public void shouldThrowOnInvalidIssuedAtIfPresent() throws Exception { exception.expect(InvalidClaimException.class); exception.expectMessage(startsWith("The Token can't be used before")); Clock clock = mock(Clock.class); when(clock.getToday()).thenReturn(new Date(DATE_TOKEN_MS_VALUE - 1000)); String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0Nzc1OTJ9.0WJky9eLN7kuxLyZlmbcXRL3Wy8hLoNCEk5CCl2M4lo"; JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWTVerifier.init(Algorithm.HMAC256("secret")); verification .build(clock) .verify(token); } @Test public void shouldValidateIssuedAtIfPresent() throws Exception { Clock clock = mock(Clock.class); when(clock.getToday()).thenReturn(new Date(DATE_TOKEN_MS_VALUE)); String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0Nzc1OTJ9.0WJky9eLN7kuxLyZlmbcXRL3Wy8hLoNCEk5CCl2M4lo"; JWTVerifier.BaseVerification verification = (JWTVerifier.BaseVerification) JWTVerifier.init(Algorithm.HMAC256("secret")); DecodedJWT jwt = verification .build(clock) .verify(token); assertThat(jwt, is(notNullValue())); } @Test public void shouldThrowOnNegativeIssuedAtLeeway() throws Exception { exception.expect(IllegalArgumentException.class); exception.expectMessage("Leeway value can't be negative."); Algorithm algorithm = mock(Algorithm.class); JWTVerifier.init(algorithm) .acceptIssuedAt(-1); } @Test public void shouldValidateJWTId() throws Exception { String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJqd3RfaWRfMTIzIn0.0kegfXUvwOYioP8PDaLMY1IlV8HOAzSVz3EGL7-jWF4"; DecodedJWT jwt = JWTVerifier.init(Algorithm.HMAC256("secret")) .withJWTId("jwt_id_123") .build() .verify(token); assertThat(jwt, is(notNullValue())); } @Test public void shouldThrowOnInvalidJWTId() throws Exception { exception.expect(InvalidClaimException.class); exception.expectMessage("The Claim 'jti' value doesn't match the required one."); String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJqd3RfaWRfMTIzIn0.0kegfXUvwOYioP8PDaLMY1IlV8HOAzSVz3EGL7-jWF4"; JWTVerifier.init(Algorithm.HMAC256("secret")) .withJWTId("invalid") .build() .verify(token); } @Test public void shouldRemoveClaimWhenPassingNull() throws Exception { Algorithm algorithm = mock(Algorithm.class); JWTVerifier verifier = JWTVerifier.init(algorithm) .withIssuer("iss") .withIssuer(null) .build(); assertThat(verifier.claims, is(notNullValue())); assertThat(verifier.claims, not(hasKey("iss"))); } @Test public void shouldSkipClaimValidationsIfNoClaimsRequired() throws Exception { String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.t-IDcSemACt8x4iTMCda8Yhe3iZaWbvV5XKSTbuAn0M"; DecodedJWT jwt = JWTVerifier.init(Algorithm.HMAC256("secret")) .build() .verify(token); assertThat(jwt, is(notNullValue())); } }