Document JwtGrantedAuthoritiesConverter Features

Fixes gh-8176
This commit is contained in:
Josh Cummings 2020-03-24 14:38:12 -06:00
parent 93ed92cc94
commit 933104d2d6
No known key found for this signature in database
GPG Key ID: 49EF60DD7FF83443
1 changed files with 59 additions and 57 deletions

View File

@ -629,15 +629,19 @@ However, there are a number of circumstances where this default is insufficient.
For example, some authorization servers don't use the `scope` attribute, but instead have their own custom attribute.
Or, at other times, the resource server may need to adapt the attribute or a composition of attributes into internalized authorities.
To this end, the DSL exposes `jwtAuthenticationConverter()`:
To this end, the DSL exposes `jwtAuthenticationConverter()`, which is responsible for converting a `Jwt` into an `Authentication`.
.Authorities Extractor Configuration
As part of its configuration, we can supply a subsidiary converter to go from `Jwt` to a `Collection` of granted authorities.
Let's say that that your authorization server communicates authorities in a custom claim called `authorities`.
In that case, you can configure the claim that `JwtAuthenticationConverter` should inspect, like so:
.Authorities Claim Configuration
====
.Java
[source,java,role="primary"]
----
@EnableWebSecurity
public class DirectlyConfiguredJwkSetUri extends WebSecurityConfigurerAdapter {
public class CustomAuthoritiesClaimName extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) {
http
.authorizeRequests(authorize -> authorize
@ -645,49 +649,22 @@ public class DirectlyConfiguredJwkSetUri extends WebSecurityConfigurerAdapter {
)
.oauth2ResourceServer(oauth2 -> oauth2
.jwt(jwt -> jwt
.jwtAuthenticationConverter(grantedAuthoritiesExtractor())
.jwtAuthenticationConverter(jwtAuthenticationConverter())
)
);
}
}
Converter<Jwt, AbstractAuthenticationToken> grantedAuthoritiesExtractor() {
JwtAuthenticationConverter jwtAuthenticationConverter =
new JwtAuthenticationConverter();
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter
(new GrantedAuthoritiesExtractor());
JwtAuthenticationConverter jwtAuthenticationConverter() {
JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
grantedAuthoritiesConverter.setAuthoritiesClaimName("authorities");
JwtAuthenticationConverter authenticationConverter = new JwtAuthenticationConverter();
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(authoritiesConverter);
return jwtAuthenticationConverter;
}
----
.Kotlin
[source,kotlin,role="secondary"]
----
@EnableWebSecurity
class DirectlyConfiguredJwkSetUri : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http {
authorizeRequests {
authorize(anyRequest, authenticated)
}
oauth2ResourceServer {
jwt {
jwtAuthenticationConverter = grantedAuthoritiesExtractor()
}
}
}
}
private fun grantedAuthoritiesExtractor(): JwtAuthenticationConverter {
val jwtAuthenticationConverter = JwtAuthenticationConverter()
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(GrantedAuthoritiesExtractor())
return jwtAuthenticationConverter
}
}
----
.Xml
[source,xml,role="secondary"]
----
@ -696,41 +673,66 @@ class DirectlyConfiguredJwkSetUri : WebSecurityConfigurerAdapter() {
<intercept-uri pattern="/messages/**" access="hasAuthority('SCOPE_messages')"/>
<oauth2-resource-server>
<jwt jwk-set-uri="https://idp.example.org/.well-known/jwks.json"
jwt-authentication-converter-ref="grantedAuthoritiesExtractor"/>
jwt-authentication-converter-ref="jwtAuthenticationConverter"/>
</oauth2-resource-server>
</http>
<bean id="grantedAuthoritiesExtractor"
<bean id="jwtAuthenticationConverter"
class="org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter">
<property name="jwtGrantedAuthoritiesConverter">
<bean class="my.custom.GrantedAuthoritiesConverter"/>
</property>
<property name="jwtGrantedAuthoritiesConverter" ref="jwtGrantedAuthoritiesConverter"/>
</bean>
<bean id="jwtGrantedAuthoritiesConverter"
class="org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter">
<property name="authoritiesClaimName" value="authorities"/>
</bean>
----
====
which is responsible for converting a `Jwt` into an `Authentication`.
As part of its configuration, we can supply a subsidiary converter to go from `Jwt` to a `Collection` of granted authorities.
You can also configure the authority prefix to be different as well.
Instead of prefixing each authority with `SCOPE_`, you can change it to `ROLE_` like so:
That final converter might be something like `GrantedAuthoritiesExtractor` below:
[source,java]
.Authorities Prefix Configuration
====
.Java
[source,java,role="primary"]
----
static class GrantedAuthoritiesExtractor
implements Converter<Jwt, Collection<GrantedAuthority>> {
JwtAuthenticationConverter jwtAuthenticationConverter() {
JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
grantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");
public Collection<GrantedAuthority> convert(Jwt jwt) {
Collection<?> authorities = (Collection<?>)
jwt.getClaims().getOrDefault("mycustomclaim", Collections.emptyList());
return authorities.stream()
.map(Object::toString)
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
}
JwtAuthenticationConverter authenticationConverter = new JwtAuthenticationConverter();
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(authoritiesConverter);
return jwtAuthenticationConverter;
}
----
.Xml
[source,xml,role="secondary"]
----
<http>
<intercept-uri pattern="/contacts/**" access="hasAuthority('SCOPE_contacts')"/>
<intercept-uri pattern="/messages/**" access="hasAuthority('SCOPE_messages')"/>
<oauth2-resource-server>
<jwt jwk-set-uri="https://idp.example.org/.well-known/jwks.json"
jwt-authentication-converter-ref="jwtAuthenticationConverter"/>
</oauth2-resource-server>
</http>
<bean id="jwtAuthenticationConverter"
class="org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter">
<property name="jwtGrantedAuthoritiesConverter" ref="jwtGrantedAuthoritiesConverter"/>
</bean>
<bean id="jwtGrantedAuthoritiesConverter"
class="org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter">
<property name="authorityPrefix" value="ROLE_"/>
</bean>
----
====
Or, you can remove the prefix altogether by calling `JwtGrantedAuthoritiesConverter#setAuthorityPrefix("")`.
For more flexibility, the DSL supports entirely replacing the converter with any class that implements `Converter<Jwt, AbstractAuthenticationToken>`:
[source,java]