|
24 | 24 | import org.apache.commons.logging.Log;
|
25 | 25 | import org.apache.commons.logging.LogFactory;
|
26 | 26 |
|
| 27 | +import org.springframework.core.ParameterizedTypeReference; |
27 | 28 | import org.springframework.core.convert.converter.Converter;
|
28 | 29 | import org.springframework.core.log.LogMessage;
|
| 30 | +import org.springframework.expression.Expression; |
| 31 | +import org.springframework.expression.ExpressionException; |
29 | 32 | import org.springframework.security.core.GrantedAuthority;
|
30 | 33 | import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
31 | 34 | import org.springframework.security.oauth2.jwt.Jwt;
|
@@ -55,6 +58,8 @@ public final class JwtGrantedAuthoritiesConverter implements Converter<Jwt, Coll
|
55 | 58 |
|
56 | 59 | private String authoritiesClaimName;
|
57 | 60 |
|
| 61 | + private Expression authoritiesClaimExpression; |
| 62 | + |
58 | 63 | /**
|
59 | 64 | * Extract {@link GrantedAuthority}s from the given {@link Jwt}.
|
60 | 65 | * @param jwt The {@link Jwt} token
|
@@ -117,16 +122,38 @@ private String getAuthoritiesClaimName(Jwt jwt) {
|
117 | 122 | return null;
|
118 | 123 | }
|
119 | 124 |
|
| 125 | + /** |
| 126 | + * Sets the expression for extracting the token claim to use for mapping {@link GrantedAuthority |
| 127 | + * authorities} by this converter. |
| 128 | + * Note that this takes precedence over {@link #setAuthoritiesClaimName(String)}. |
| 129 | + * @param authoritiesClaimExpression The token claim SpEL Expression to map authorities |
| 130 | + * @since 6.5 |
| 131 | + */ |
| 132 | + public void setAuthoritiesClaimExpression(Expression authoritiesClaimExpression) { |
| 133 | + Assert.notNull(authoritiesClaimExpression, "authoritiesClaimExpression must not be null"); |
| 134 | + this.authoritiesClaimExpression = authoritiesClaimExpression; |
| 135 | + } |
| 136 | + |
120 | 137 | private Collection<String> getAuthorities(Jwt jwt) {
|
121 |
| - String claimName = getAuthoritiesClaimName(jwt); |
122 |
| - if (claimName == null) { |
123 |
| - this.logger.trace("Returning no authorities since could not find any claims that might contain scopes"); |
124 |
| - return Collections.emptyList(); |
125 |
| - } |
126 |
| - if (this.logger.isTraceEnabled()) { |
127 |
| - this.logger.trace(LogMessage.format("Looking for scopes in claim %s", claimName)); |
| 138 | + |
| 139 | + Object authorities; |
| 140 | + if (authoritiesClaimExpression != null) { |
| 141 | + try { |
| 142 | + authorities = authoritiesClaimExpression.getValue(jwt.getClaims(), Collection.class); |
| 143 | + } catch (ExpressionException ee) { |
| 144 | + authorities = Collections.emptyList(); |
| 145 | + } |
| 146 | + } else { |
| 147 | + String claimName = getAuthoritiesClaimName(jwt); |
| 148 | + if (claimName == null) { |
| 149 | + this.logger.trace("Returning no authorities since could not find any claims that might contain scopes"); |
| 150 | + return Collections.emptyList(); |
| 151 | + } |
| 152 | + if (this.logger.isTraceEnabled()) { |
| 153 | + this.logger.trace(LogMessage.format("Looking for scopes in claim %s", claimName)); |
| 154 | + } |
| 155 | + authorities = jwt.getClaim(claimName); |
128 | 156 | }
|
129 |
| - Object authorities = jwt.getClaim(claimName); |
130 | 157 | if (authorities instanceof String) {
|
131 | 158 | if (StringUtils.hasText((String) authorities)) {
|
132 | 159 | return Arrays.asList(((String) authorities).split(this.authoritiesClaimDelimiter));
|
|
0 commit comments