Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to verify audience contains at least one of those expected #472

Merged
merged 3 commits into from
Feb 5, 2021

Conversation

jimmyjames
Copy link
Contributor

Changes

This PR adds the ability to verify that a JWT's audience claim contains at least one of the expected audiences. Currently, withAudience requires that the audience claim match the specified audience exactly.

Resolves #449

New public method:

  • withAnyOfAudience(String... audience) - verifies that the JWT's audience claim contains at least one of the specified audiences.

Details:

  • If both withAudience and withAnyOfAudience are called on the same Verification instance, an IllegalStateException will be thrown.

Alternatives considered:

  • Instead of managing the audience verification behavior with an enum, we could instead keep a boolean flag. This would mean that if both withAudience and withAnyOfAudience are used on the same Verification instance, the last one called wins. We could document that behavior, but discussion with @lbalmaceda thought it best for us to throw in that scenario.

Checklist

@jimmyjames jimmyjames added this to the v3-Next milestone Feb 2, 2021
@jimmyjames jimmyjames requested a review from a team as a code owner February 2, 2021 00:21
Copy link
Contributor

@lbalmaceda lbalmaceda left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can avoid this flag if we reuse the existing Map<String, Object> claims. We could define a new constant for AUDIENCE_EXACT vs AUDIENCE_CONTAINS and then in the switch case pick the strategy.

private void verifyClaimValues(DecodedJWT jwt, Map.Entry<String, Object> entry) {
switch (entry.getKey()) {
case PublicClaims.AUDIENCE:
assertValidAudienceClaim(jwt.getAudience(), (List<String>) entry.getValue());
break;
case PublicClaims.EXPIRES_AT:

The only thing I'd be careful of is not exposing these two new constants, as they are rather used internally.

The flag would go away and we could even skip checking and throwing if a different audience verification strategy was already set, as both could now co-exist. Thoughts?

@jimmyjames
Copy link
Contributor Author

I think we can avoid this flag if we reuse the existing Map<String, Object> claims. We could define a new constant for AUDIENCE_EXACT vs AUDIENCE_CONTAINS and then in the switch case pick the strategy.

private void verifyClaimValues(DecodedJWT jwt, Map.Entry<String, Object> entry) {
switch (entry.getKey()) {
case PublicClaims.AUDIENCE:
assertValidAudienceClaim(jwt.getAudience(), (List<String>) entry.getValue());
break;
case PublicClaims.EXPIRES_AT:

Yes, we could do that. It avoids adding another parameter to the JWTVerifier constructor, which is good. However, I do wonder if it makes the code a bit more confusing, as we'd be using non-standard claim keys for the different audience verification strategies. It's an internally managed map of the expected values, but I could see that causing some confusion for future maintainers. It's a trade-off, no additional constructor param or using non-standard claim keys in the internal verification logic.

The flag would go away and we could even skip checking and throwing if a different audience verification strategy was already set, as both could now co-exist. Thoughts?

Can you think of a use case where both strategies would be used on the same verification? Or, we don't need to throw an exception if both are used, and instead could let the last one configured win. If using new custom claim keys to determine how the audience should be validated, we'd just remove the other claim from the expectations (e.g., withAudience would first remove any claim entries with the AUDIENCE_CONTAINS key).

@jimmyjames
Copy link
Contributor Author

Yes, we could do that. It avoids adding another parameter to the JWTVerifier constructor, which is good. However, I do wonder if it makes the code a bit more confusing, as we'd be using non-standard claim keys for the different audience verification strategies. It's an internally managed map of the expected values, but I could see that causing some confusion for future maintainers. It's a trade-off, no additional constructor param or using non-standard claim keys in the internal verification logic.

The flag would go away and we could even skip checking and throwing if a different audience verification strategy was already set, as both could now co-exist. Thoughts?

Can you think of a use case where both strategies would be used on the same verification? Or, we don't need to throw an exception if both are used, and instead could let the last one configured win. If using new custom claim keys to determine how the audience should be validated, we'd just remove the other claim from the expectations (e.g., withAudience would first remove any claim entries with the AUDIENCE_CONTAINS key).

We discussed offline, and will proceed to manage the expected audience values internally using different keys for the desired verification behavior. We will also update this PR such that if both withAudience and withAnyAudience are used on the same Verification instance, the audience verification behavior will be overridden (last one wins).

lbalmaceda
lbalmaceda previously approved these changes Feb 4, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Multiple Audience Support
2 participants