diff --git a/lib/src/main/java/com/auth0/jwt/JWTVerifier.java b/lib/src/main/java/com/auth0/jwt/JWTVerifier.java index 6eea86bb..a1c7f82b 100644 --- a/lib/src/main/java/com/auth0/jwt/JWTVerifier.java +++ b/lib/src/main/java/com/auth0/jwt/JWTVerifier.java @@ -61,12 +61,12 @@ public static class BaseVerification implements Verification { /** * Require a specific Issuer ("iss") claim. * - * @param issuer the required Issuer value + * @param issuer the required Issuer value. If multiple values are given, the claim must at least match one of them * @return this same Verification instance. */ @Override - public Verification withIssuer(String issuer) { - requireClaim(PublicClaims.ISSUER, issuer); + public Verification withIssuer(String... issuer) { + requireClaim(PublicClaims.ISSUER, issuer == null ? null : Arrays.asList(issuer)); return this; } @@ -90,7 +90,7 @@ public Verification withSubject(String subject) { */ @Override public Verification withAudience(String... audience) { - requireClaim(PublicClaims.AUDIENCE, Arrays.asList(audience)); + requireClaim(PublicClaims.AUDIENCE, audience == null ? null : Arrays.asList(audience)); return this; } @@ -398,7 +398,6 @@ private void verifyClaims(DecodedJWT jwt, Map claims) throws Tok for (Map.Entry entry : claims.entrySet()) { switch (entry.getKey()) { case PublicClaims.AUDIENCE: - //noinspection unchecked assertValidAudienceClaim(jwt.getAudience(), (List) entry.getValue()); break; case PublicClaims.EXPIRES_AT: @@ -411,7 +410,7 @@ private void verifyClaims(DecodedJWT jwt, Map claims) throws Tok assertValidDateClaim(jwt.getNotBefore(), (Long) entry.getValue(), false); break; case PublicClaims.ISSUER: - assertValidStringClaim(entry.getKey(), jwt.getIssuer(), (String) entry.getValue()); + assertValidIssuerClaim(jwt.getIssuer(), (List) entry.getValue()); break; case PublicClaims.JWT_ID: assertValidStringClaim(entry.getKey(), jwt.getId(), (String) entry.getValue()); @@ -486,4 +485,10 @@ private void assertValidAudienceClaim(List audience, List value) throw new InvalidClaimException("The Claim 'aud' value doesn't contain the required audience."); } } + + private void assertValidIssuerClaim(String issuer, List value) { + if (issuer == null || !value.contains(issuer)) { + throw new InvalidClaimException("The Claim 'iss' value doesn't match the required issuer."); + } + } } diff --git a/lib/src/main/java/com/auth0/jwt/interfaces/Verification.java b/lib/src/main/java/com/auth0/jwt/interfaces/Verification.java index a38468ab..41b1ce3e 100644 --- a/lib/src/main/java/com/auth0/jwt/interfaces/Verification.java +++ b/lib/src/main/java/com/auth0/jwt/interfaces/Verification.java @@ -5,7 +5,7 @@ import java.util.Date; public interface Verification { - Verification withIssuer(String issuer); + Verification withIssuer(String... issuer); Verification withSubject(String subject); diff --git a/lib/src/test/java/com/auth0/jwt/JWTVerifierTest.java b/lib/src/test/java/com/auth0/jwt/JWTVerifierTest.java index d7bcdd2c..e297c59c 100644 --- a/lib/src/test/java/com/auth0/jwt/JWTVerifierTest.java +++ b/lib/src/test/java/com/auth0/jwt/JWTVerifierTest.java @@ -51,10 +51,22 @@ public void shouldValidateIssuer() throws Exception { assertThat(jwt, is(notNullValue())); } + @Test + public void shouldValidateMultipleIssuers() { + String auth0Token = "eyJhbGciOiJIUzI1NiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mZ0m_N1J4PgeqWmi903JuUoDRZDBPB7HwkS4nVyWH1M"; + String otherIssuertoken = "eyJhbGciOiJIUzI1NiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJvdGhlcklzc3VlciJ9.k4BCOJJl-c0_Y-49VD_mtt-u0QABKSV5i3W-RKc74co"; + JWTVerifier verifier = JWTVerifier.init(Algorithm.HMAC256("secret")) + .withIssuer("otherIssuer", "auth0") + .build(); + + assertThat(verifier.verify(auth0Token), is(notNullValue())); + assertThat(verifier.verify(otherIssuertoken), is(notNullValue())); + } + @Test public void shouldThrowOnInvalidIssuer() throws Exception { exception.expect(InvalidClaimException.class); - exception.expectMessage("The Claim 'iss' value doesn't match the required one."); + exception.expectMessage("The Claim 'iss' value doesn't match the required issuer."); String token = "eyJhbGciOiJIUzI1NiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mZ0m_N1J4PgeqWmi903JuUoDRZDBPB7HwkS4nVyWH1M"; JWTVerifier.init(Algorithm.HMAC256("secret")) .withIssuer("invalid") @@ -62,6 +74,18 @@ public void shouldThrowOnInvalidIssuer() throws Exception { .verify(token); } + @Test + public void shouldThrowOnNullIssuer() throws Exception { + exception.expect(InvalidClaimException.class); + exception.expectMessage("The Claim 'iss' value doesn't match the required issuer."); + + String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.t-IDcSemACt8x4iTMCda8Yhe3iZaWbvV5XKSTbuAn0M"; + JWTVerifier.init(Algorithm.HMAC256("secret")) + .withIssuer("auth0") + .build() + .verify(token); + } + @Test public void shouldValidateSubject() throws Exception { String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.Rq8IxqeX7eA6GgYxlcHdPFVRNFFZc5rEI3MQTZZbK3I"; @@ -126,6 +150,18 @@ public void shouldThrowOnInvalidAudience() throws Exception { .verify(token); } + @Test + public void shouldRemoveAudienceWhenPassingNull() throws Exception { + Algorithm algorithm = mock(Algorithm.class); + JWTVerifier verifier = JWTVerifier.init(algorithm) + .withAudience("John") + .withAudience(null) + .build(); + + assertThat(verifier.claims, is(notNullValue())); + assertThat(verifier.claims, not(hasKey("aud"))); + } + @Test public void shouldThrowOnNullCustomClaimName() throws Exception { exception.expect(IllegalArgumentException.class);