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
This commit is contained in:
parent
abc90280e0
commit
b45e57cc40
|
@ -25,6 +25,7 @@ import org.springframework.core.convert.converter.Converter;
|
|||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
|
@ -40,6 +41,8 @@ public final class JwtGrantedAuthoritiesConverter implements Converter<Jwt, Coll
|
|||
private static final Collection<String> WELL_KNOWN_AUTHORITIES_CLAIM_NAMES =
|
||||
Arrays.asList("scope", "scp");
|
||||
|
||||
private String authorityPrefix = DEFAULT_AUTHORITY_PREFIX;
|
||||
|
||||
/**
|
||||
* Extract {@link GrantedAuthority}s from the given {@link Jwt}.
|
||||
*
|
||||
|
@ -50,11 +53,23 @@ public final class JwtGrantedAuthoritiesConverter implements Converter<Jwt, Coll
|
|||
public Collection<GrantedAuthority> convert(Jwt jwt) {
|
||||
Collection<GrantedAuthority> grantedAuthorities = new ArrayList<>();
|
||||
for (String authority : getAuthorities(jwt)) {
|
||||
grantedAuthorities.add(new SimpleGrantedAuthority(DEFAULT_AUTHORITY_PREFIX + authority));
|
||||
grantedAuthorities.add(new SimpleGrantedAuthority(this.authorityPrefix + authority));
|
||||
}
|
||||
return grantedAuthorities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the prefix to use for {@link GrantedAuthority authorities} mapped by this converter.
|
||||
* Defaults to {@link JwtGrantedAuthoritiesConverter#DEFAULT_AUTHORITY_PREFIX}.
|
||||
*
|
||||
* @param authorityPrefix The authority prefix
|
||||
* @since 5.2
|
||||
*/
|
||||
public void setAuthorityPrefix(String authorityPrefix) {
|
||||
Assert.hasText(authorityPrefix, "authorityPrefix cannot be empty");
|
||||
this.authorityPrefix = authorityPrefix;
|
||||
}
|
||||
|
||||
private String getAuthoritiesClaimName(Jwt jwt) {
|
||||
for (String claimName : WELL_KNOWN_AUTHORITIES_CLAIM_NAMES) {
|
||||
if (jwt.containsClaim(claimName)) {
|
||||
|
|
|
@ -40,46 +40,75 @@ import org.springframework.security.oauth2.jwt.Jwt;
|
|||
* @since 5.2
|
||||
*/
|
||||
public class JwtGrantedAuthoritiesConverterTests {
|
||||
private JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
|
||||
|
||||
@Test
|
||||
public void convertWhenTokenHasScopeAttributeThenTranslatedToAuthorities() {
|
||||
Jwt jwt = this.jwt(Collections.singletonMap("scope", "message:read message:write"));
|
||||
|
||||
Collection<GrantedAuthority> authorities = this.jwtGrantedAuthoritiesConverter.convert(jwt);
|
||||
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
|
||||
Collection<GrantedAuthority> authorities = jwtGrantedAuthoritiesConverter.convert(jwt);
|
||||
|
||||
assertThat(authorities).containsExactly(
|
||||
new SimpleGrantedAuthority("SCOPE_message:read"),
|
||||
new SimpleGrantedAuthority("SCOPE_message:write"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertWithCustomAuthorityPrefixWhenTokenHasScopeAttributeThenTranslatedToAuthorities() {
|
||||
Jwt jwt = this.jwt(Collections.singletonMap("scope", "message:read message:write"));
|
||||
|
||||
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
|
||||
jwtGrantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");
|
||||
Collection<GrantedAuthority> authorities = jwtGrantedAuthoritiesConverter.convert(jwt);
|
||||
|
||||
assertThat(authorities).containsExactly(
|
||||
new SimpleGrantedAuthority("ROLE_message:read"),
|
||||
new SimpleGrantedAuthority("ROLE_message:write"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertWhenTokenHasEmptyScopeAttributeThenTranslatedToNoAuthorities() {
|
||||
Jwt jwt = this.jwt(Collections.singletonMap("scope", ""));
|
||||
|
||||
Collection<GrantedAuthority> authorities = this.jwtGrantedAuthoritiesConverter.convert(jwt);
|
||||
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
|
||||
Collection<GrantedAuthority> authorities = jwtGrantedAuthoritiesConverter.convert(jwt);
|
||||
|
||||
assertThat(authorities).containsExactly();
|
||||
assertThat(authorities).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertWhenTokenHasScpAttributeThenTranslatedToAuthorities() {
|
||||
Jwt jwt = this.jwt(Collections.singletonMap("scp", Arrays.asList("message:read", "message:write")));
|
||||
|
||||
Collection<GrantedAuthority> authorities = this.jwtGrantedAuthoritiesConverter.convert(jwt);
|
||||
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
|
||||
Collection<GrantedAuthority> authorities = jwtGrantedAuthoritiesConverter.convert(jwt);
|
||||
|
||||
assertThat(authorities).containsExactly(
|
||||
new SimpleGrantedAuthority("SCOPE_message:read"),
|
||||
new SimpleGrantedAuthority("SCOPE_message:write"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertWithCustomAuthorityPrefixWhenTokenHasScpAttributeThenTranslatedToAuthorities() {
|
||||
Jwt jwt = this.jwt(Collections.singletonMap("scp", Arrays.asList("message:read", "message:write")));
|
||||
|
||||
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
|
||||
jwtGrantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");
|
||||
Collection<GrantedAuthority> authorities = jwtGrantedAuthoritiesConverter.convert(jwt);
|
||||
|
||||
assertThat(authorities).containsExactly(
|
||||
new SimpleGrantedAuthority("ROLE_message:read"),
|
||||
new SimpleGrantedAuthority("ROLE_message:write"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertWhenTokenHasEmptyScpAttributeThenTranslatedToNoAuthorities() {
|
||||
Jwt jwt = this.jwt(Maps.newHashMap("scp", Arrays.asList()));
|
||||
Jwt jwt = this.jwt(Maps.newHashMap("scp", Collections.emptyList()));
|
||||
|
||||
Collection<GrantedAuthority> authorities = this.jwtGrantedAuthoritiesConverter.convert(jwt);
|
||||
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
|
||||
Collection<GrantedAuthority> authorities = jwtGrantedAuthoritiesConverter.convert(jwt);
|
||||
|
||||
assertThat(authorities).containsExactly();
|
||||
assertThat(authorities).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -89,7 +118,8 @@ public class JwtGrantedAuthoritiesConverterTests {
|
|||
claims.put("scope", "missive:read missive:write");
|
||||
Jwt jwt = this.jwt(claims);
|
||||
|
||||
Collection<GrantedAuthority> authorities = this.jwtGrantedAuthoritiesConverter.convert(jwt);
|
||||
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
|
||||
Collection<GrantedAuthority> authorities = jwtGrantedAuthoritiesConverter.convert(jwt);
|
||||
|
||||
assertThat(authorities).containsExactly(
|
||||
new SimpleGrantedAuthority("SCOPE_missive:read"),
|
||||
|
@ -103,9 +133,10 @@ public class JwtGrantedAuthoritiesConverterTests {
|
|||
claims.put("scope", "");
|
||||
Jwt jwt = this.jwt(claims);
|
||||
|
||||
Collection<GrantedAuthority> authorities = this.jwtGrantedAuthoritiesConverter.convert(jwt);
|
||||
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
|
||||
Collection<GrantedAuthority> authorities = jwtGrantedAuthoritiesConverter.convert(jwt);
|
||||
|
||||
assertThat(authorities).containsExactly();
|
||||
assertThat(authorities).isEmpty();
|
||||
}
|
||||
|
||||
private Jwt jwt(Map<String, Object> claims) {
|
||||
|
|
Loading…
Reference in New Issue