auth0 / java-jwt

Java implementation of JSON Web Token (JWT)
MIT License
5.89k stars 921 forks source link

Support verification for anyOfClaim #623

Closed jlorenzen closed 2 years ago

jlorenzen commented 2 years ago

Describe the problem you'd like to have solved

It would be extremely useful if the Verification interface supported the ability to verify whether any JWT claim contains a value from a list of expected values.

Describe the ideal solution

Ideally a verification method similar to withAnyOfAudience but for any claim. Specifically we need this to verify the client_id claim contains a value from a list of values.

For example:

JWT
  .require(algorithm)
  .withAnyOfClaim("client_id", "clientIdValue1", "clientIdValue2")
  .build()

Alternatives and current work-arounds

  1. Similar feature request to #474
  2. Attempted to see if I could add a kotlin extension function, but the BaseVerification.expectedChecks variable is private
  3. Considered extending BaseVerification, but that's not really useful as it's locked down tightly as well
  4. As suggested in #474, might have to perform custom verification after calling JWTVerifier.verify. Would work but not ideal.

Additional information, if any

  1. If support was added for this method, I could see the existing withAnyOfAudience calling it as it's the same type of check just with a different claim.
  2. This requirement has become increasingly necessary as our API is verifying JWTs from different clients that are using the OAuth2 client_credentials flow.

I'd be happy to submit a PR if this feature request was deemed a worthy addition to the existing API.

jimmyjames commented 2 years ago

👋 hi @jlorenzen, thanks for the details.

In v4 we added the ability to verify a claim using a provided Predicate, so that verifications such as your use case can be accommodated. A simple test to demonstrate:

@Test
public void shouldSuccessfullyVerifyClaimWithPredicate2() {
    List<String> listClaim = Arrays.asList("one", "two");

    String jwt = JWTCreator.init()
            .withClaim("listClaim", listClaim)
            .sign(Algorithm.HMAC256("USE-BETTER-SECRET"));

    JWTVerifier verifier = JWTVerifier.init(Algorithm.HMAC256("USE-BETTER-SECRET"))
            .withClaim("listClaim", (claim, decodedJWT) -> claim.asList(String.class).contains("one"))
            .build();

    DecodedJWT decodedJWT = verifier.verify(jwt);
    assertThat(decodedJWT, is(notNullValue()));
}
jlorenzen commented 2 years ago

@jimmyjames That's perfect! I can't believe I didn't see that. Thanks