Skip to content

Improve authoritiesClaimName validation in JwtGrantedAuthoritiesConverter #17247

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -53,7 +53,9 @@ public final class JwtGrantedAuthoritiesConverter implements Converter<Jwt, Coll

private String authoritiesClaimDelimiter = DEFAULT_AUTHORITIES_CLAIM_DELIMITER;

private String authoritiesClaimName;
private Collection<String> authoritiesClaimNames = WELL_KNOWN_AUTHORITIES_CLAIM_NAMES;

private boolean isExplicitlySet = false;

/**
* Extract {@link GrantedAuthority}s from the given {@link Jwt}.
Expand Down Expand Up @@ -102,14 +104,15 @@ public void setAuthoritiesClaimDelimiter(String authoritiesClaimDelimiter) {
*/
public void setAuthoritiesClaimName(String authoritiesClaimName) {
Assert.hasText(authoritiesClaimName, "authoritiesClaimName cannot be empty");
this.authoritiesClaimName = authoritiesClaimName;
this.authoritiesClaimNames = Collections.singletonList(authoritiesClaimName);
this.isExplicitlySet = true;
}

private String getAuthoritiesClaimName(Jwt jwt) {
if (this.authoritiesClaimName != null) {
return this.authoritiesClaimName;
if (this.isExplicitlySet) {
Copy link
Contributor Author

@chanbinme chanbinme Jun 19, 2025

Choose a reason for hiding this comment

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

Hi @jzheaux,

I've implemented the refactoring as suggested, but I noticed an important behavioral difference that I wanted to discuss:

Original behavior:
When authoritiesClaimName is explicitly set → return it directly without JWT validation
When using default claim names → return the first claim name that exists in the JWT

Initial refactoring attempt:
All claim names go through JWT validation, which changes the behavior for explicitly set claim names

My solution:
To preserve the original behavior, I added an isExplicitlySet flag that tracks whether the claim name was explicitly configured. This ensures:

  • Explicitly set claim names are returned without JWT validation (original behavior)
  • Default claim names are validated against the JWT (original behavior)
  • Null checks are eliminated since authoritiesClaimNames is always initialized

Would you prefer this approach, or would you like to intentionally change the behavior to always validate claim names against the JWT? I wanted to confirm the intended behavior before finalizing the implementation.

The changes include:
✅ Changed authoritiesClaimName to Collection<String> authoritiesClaimNames
✅ Updated setAuthoritiesClaimName to use Collections.singletonList()
✅ Modified the for loop to use this.authoritiesClaimNames
✅ Removed null checks
➕ Added isExplicitlySet flag to preserve original behavior

Let me know your thoughts on this approach!

return this.authoritiesClaimNames.iterator().next();
}
for (String claimName : WELL_KNOWN_AUTHORITIES_CLAIM_NAMES) {
for (String claimName : this.authoritiesClaimNames) {
if (jwt.hasClaim(claimName)) {
return claimName;
}
Expand Down
Loading