Skip to content

Commit b45e57c

Browse files
andifalkjzheaux
authored andcommitted
Add setter for authority prefix in JwtGrantedAuthoritiesConverter
Prior to this change mapped authorities are always prefixed with default value 'SCOPE_'. To change this default behaviour the converter had to be replaced completely with a custom one. This commit adds an additional setter to configure a custom authority prefix like e.g. 'ROLE_'. Without specifying a custom prefix the default prefix still remains 'SCOPE_'. This way existing authorization checks using the standard 'ROLE_' prefix can be reused without lots of effort. Fixes gh-7101
1 parent abc9028 commit b45e57c

File tree

2 files changed

+58
-12
lines changed

2 files changed

+58
-12
lines changed

oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtGrantedAuthoritiesConverter.java

+16-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.springframework.security.core.GrantedAuthority;
2626
import org.springframework.security.core.authority.SimpleGrantedAuthority;
2727
import org.springframework.security.oauth2.jwt.Jwt;
28+
import org.springframework.util.Assert;
2829
import org.springframework.util.StringUtils;
2930

3031
/**
@@ -40,6 +41,8 @@ public final class JwtGrantedAuthoritiesConverter implements Converter<Jwt, Coll
4041
private static final Collection<String> WELL_KNOWN_AUTHORITIES_CLAIM_NAMES =
4142
Arrays.asList("scope", "scp");
4243

44+
private String authorityPrefix = DEFAULT_AUTHORITY_PREFIX;
45+
4346
/**
4447
* Extract {@link GrantedAuthority}s from the given {@link Jwt}.
4548
*
@@ -50,11 +53,23 @@ public final class JwtGrantedAuthoritiesConverter implements Converter<Jwt, Coll
5053
public Collection<GrantedAuthority> convert(Jwt jwt) {
5154
Collection<GrantedAuthority> grantedAuthorities = new ArrayList<>();
5255
for (String authority : getAuthorities(jwt)) {
53-
grantedAuthorities.add(new SimpleGrantedAuthority(DEFAULT_AUTHORITY_PREFIX + authority));
56+
grantedAuthorities.add(new SimpleGrantedAuthority(this.authorityPrefix + authority));
5457
}
5558
return grantedAuthorities;
5659
}
5760

61+
/**
62+
* Sets the prefix to use for {@link GrantedAuthority authorities} mapped by this converter.
63+
* Defaults to {@link JwtGrantedAuthoritiesConverter#DEFAULT_AUTHORITY_PREFIX}.
64+
*
65+
* @param authorityPrefix The authority prefix
66+
* @since 5.2
67+
*/
68+
public void setAuthorityPrefix(String authorityPrefix) {
69+
Assert.hasText(authorityPrefix, "authorityPrefix cannot be empty");
70+
this.authorityPrefix = authorityPrefix;
71+
}
72+
5873
private String getAuthoritiesClaimName(Jwt jwt) {
5974
for (String claimName : WELL_KNOWN_AUTHORITIES_CLAIM_NAMES) {
6075
if (jwt.containsClaim(claimName)) {

oauth2/oauth2-resource-server/src/test/java/org/springframework/security/oauth2/server/resource/authentication/JwtGrantedAuthoritiesConverterTests.java

+42-11
Original file line numberDiff line numberDiff line change
@@ -40,46 +40,75 @@
4040
* @since 5.2
4141
*/
4242
public class JwtGrantedAuthoritiesConverterTests {
43-
private JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
4443

4544
@Test
4645
public void convertWhenTokenHasScopeAttributeThenTranslatedToAuthorities() {
4746
Jwt jwt = this.jwt(Collections.singletonMap("scope", "message:read message:write"));
4847

49-
Collection<GrantedAuthority> authorities = this.jwtGrantedAuthoritiesConverter.convert(jwt);
48+
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
49+
Collection<GrantedAuthority> authorities = jwtGrantedAuthoritiesConverter.convert(jwt);
5050

5151
assertThat(authorities).containsExactly(
5252
new SimpleGrantedAuthority("SCOPE_message:read"),
5353
new SimpleGrantedAuthority("SCOPE_message:write"));
5454
}
5555

56+
@Test
57+
public void convertWithCustomAuthorityPrefixWhenTokenHasScopeAttributeThenTranslatedToAuthorities() {
58+
Jwt jwt = this.jwt(Collections.singletonMap("scope", "message:read message:write"));
59+
60+
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
61+
jwtGrantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");
62+
Collection<GrantedAuthority> authorities = jwtGrantedAuthoritiesConverter.convert(jwt);
63+
64+
assertThat(authorities).containsExactly(
65+
new SimpleGrantedAuthority("ROLE_message:read"),
66+
new SimpleGrantedAuthority("ROLE_message:write"));
67+
}
68+
5669
@Test
5770
public void convertWhenTokenHasEmptyScopeAttributeThenTranslatedToNoAuthorities() {
5871
Jwt jwt = this.jwt(Collections.singletonMap("scope", ""));
5972

60-
Collection<GrantedAuthority> authorities = this.jwtGrantedAuthoritiesConverter.convert(jwt);
73+
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
74+
Collection<GrantedAuthority> authorities = jwtGrantedAuthoritiesConverter.convert(jwt);
6175

62-
assertThat(authorities).containsExactly();
76+
assertThat(authorities).isEmpty();
6377
}
6478

6579
@Test
6680
public void convertWhenTokenHasScpAttributeThenTranslatedToAuthorities() {
6781
Jwt jwt = this.jwt(Collections.singletonMap("scp", Arrays.asList("message:read", "message:write")));
6882

69-
Collection<GrantedAuthority> authorities = this.jwtGrantedAuthoritiesConverter.convert(jwt);
83+
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
84+
Collection<GrantedAuthority> authorities = jwtGrantedAuthoritiesConverter.convert(jwt);
7085

7186
assertThat(authorities).containsExactly(
7287
new SimpleGrantedAuthority("SCOPE_message:read"),
7388
new SimpleGrantedAuthority("SCOPE_message:write"));
7489
}
7590

91+
@Test
92+
public void convertWithCustomAuthorityPrefixWhenTokenHasScpAttributeThenTranslatedToAuthorities() {
93+
Jwt jwt = this.jwt(Collections.singletonMap("scp", Arrays.asList("message:read", "message:write")));
94+
95+
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
96+
jwtGrantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");
97+
Collection<GrantedAuthority> authorities = jwtGrantedAuthoritiesConverter.convert(jwt);
98+
99+
assertThat(authorities).containsExactly(
100+
new SimpleGrantedAuthority("ROLE_message:read"),
101+
new SimpleGrantedAuthority("ROLE_message:write"));
102+
}
103+
76104
@Test
77105
public void convertWhenTokenHasEmptyScpAttributeThenTranslatedToNoAuthorities() {
78-
Jwt jwt = this.jwt(Maps.newHashMap("scp", Arrays.asList()));
106+
Jwt jwt = this.jwt(Maps.newHashMap("scp", Collections.emptyList()));
79107

80-
Collection<GrantedAuthority> authorities = this.jwtGrantedAuthoritiesConverter.convert(jwt);
108+
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
109+
Collection<GrantedAuthority> authorities = jwtGrantedAuthoritiesConverter.convert(jwt);
81110

82-
assertThat(authorities).containsExactly();
111+
assertThat(authorities).isEmpty();
83112
}
84113

85114
@Test
@@ -89,7 +118,8 @@ public void convertWhenTokenHasBothScopeAndScpThenScopeAttributeIsTranslatedToAu
89118
claims.put("scope", "missive:read missive:write");
90119
Jwt jwt = this.jwt(claims);
91120

92-
Collection<GrantedAuthority> authorities = this.jwtGrantedAuthoritiesConverter.convert(jwt);
121+
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
122+
Collection<GrantedAuthority> authorities = jwtGrantedAuthoritiesConverter.convert(jwt);
93123

94124
assertThat(authorities).containsExactly(
95125
new SimpleGrantedAuthority("SCOPE_missive:read"),
@@ -103,9 +133,10 @@ public void convertWhenTokenHasEmptyScopeAndNonEmptyScpThenScopeAttributeIsTrans
103133
claims.put("scope", "");
104134
Jwt jwt = this.jwt(claims);
105135

106-
Collection<GrantedAuthority> authorities = this.jwtGrantedAuthoritiesConverter.convert(jwt);
136+
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
137+
Collection<GrantedAuthority> authorities = jwtGrantedAuthoritiesConverter.convert(jwt);
107138

108-
assertThat(authorities).containsExactly();
139+
assertThat(authorities).isEmpty();
109140
}
110141

111142
private Jwt jwt(Map<String, Object> claims) {

0 commit comments

Comments
 (0)