Document JwtGrantedAuthoritiesConverter Features
Fixes gh-8176
This commit is contained in:
parent
93ed92cc94
commit
933104d2d6
|
@ -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.
|
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.
|
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
|
.Java
|
||||||
[source,java,role="primary"]
|
[source,java,role="primary"]
|
||||||
----
|
----
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
public class DirectlyConfiguredJwkSetUri extends WebSecurityConfigurerAdapter {
|
public class CustomAuthoritiesClaimName extends WebSecurityConfigurerAdapter {
|
||||||
protected void configure(HttpSecurity http) {
|
protected void configure(HttpSecurity http) {
|
||||||
http
|
http
|
||||||
.authorizeRequests(authorize -> authorize
|
.authorizeRequests(authorize -> authorize
|
||||||
|
@ -645,49 +649,22 @@ public class DirectlyConfiguredJwkSetUri extends WebSecurityConfigurerAdapter {
|
||||||
)
|
)
|
||||||
.oauth2ResourceServer(oauth2 -> oauth2
|
.oauth2ResourceServer(oauth2 -> oauth2
|
||||||
.jwt(jwt -> jwt
|
.jwt(jwt -> jwt
|
||||||
.jwtAuthenticationConverter(grantedAuthoritiesExtractor())
|
.jwtAuthenticationConverter(jwtAuthenticationConverter())
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Converter<Jwt, AbstractAuthenticationToken> grantedAuthoritiesExtractor() {
|
JwtAuthenticationConverter jwtAuthenticationConverter() {
|
||||||
JwtAuthenticationConverter jwtAuthenticationConverter =
|
JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
|
||||||
new JwtAuthenticationConverter();
|
grantedAuthoritiesConverter.setAuthoritiesClaimName("authorities");
|
||||||
|
|
||||||
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter
|
|
||||||
(new GrantedAuthoritiesExtractor());
|
|
||||||
|
|
||||||
|
JwtAuthenticationConverter authenticationConverter = new JwtAuthenticationConverter();
|
||||||
|
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(authoritiesConverter);
|
||||||
return jwtAuthenticationConverter;
|
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
|
.Xml
|
||||||
[source,xml,role="secondary"]
|
[source,xml,role="secondary"]
|
||||||
----
|
----
|
||||||
|
@ -696,41 +673,66 @@ class DirectlyConfiguredJwkSetUri : WebSecurityConfigurerAdapter() {
|
||||||
<intercept-uri pattern="/messages/**" access="hasAuthority('SCOPE_messages')"/>
|
<intercept-uri pattern="/messages/**" access="hasAuthority('SCOPE_messages')"/>
|
||||||
<oauth2-resource-server>
|
<oauth2-resource-server>
|
||||||
<jwt jwk-set-uri="https://idp.example.org/.well-known/jwks.json"
|
<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>
|
</oauth2-resource-server>
|
||||||
</http>
|
</http>
|
||||||
|
|
||||||
<bean id="grantedAuthoritiesExtractor"
|
<bean id="jwtAuthenticationConverter"
|
||||||
class="org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter">
|
class="org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter">
|
||||||
<property name="jwtGrantedAuthoritiesConverter">
|
<property name="jwtGrantedAuthoritiesConverter" ref="jwtGrantedAuthoritiesConverter"/>
|
||||||
<bean class="my.custom.GrantedAuthoritiesConverter"/>
|
</bean>
|
||||||
</property>
|
|
||||||
|
<bean id="jwtGrantedAuthoritiesConverter"
|
||||||
|
class="org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter">
|
||||||
|
<property name="authoritiesClaimName" value="authorities"/>
|
||||||
</bean>
|
</bean>
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
which is responsible for converting a `Jwt` into an `Authentication`.
|
You can also configure the authority prefix to be different as well.
|
||||||
As part of its configuration, we can supply a subsidiary converter to go from `Jwt` to a `Collection` of granted authorities.
|
Instead of prefixing each authority with `SCOPE_`, you can change it to `ROLE_` like so:
|
||||||
|
|
||||||
That final converter might be something like `GrantedAuthoritiesExtractor` below:
|
.Authorities Prefix Configuration
|
||||||
|
====
|
||||||
[source,java]
|
.Java
|
||||||
|
[source,java,role="primary"]
|
||||||
----
|
----
|
||||||
static class GrantedAuthoritiesExtractor
|
JwtAuthenticationConverter jwtAuthenticationConverter() {
|
||||||
implements Converter<Jwt, Collection<GrantedAuthority>> {
|
JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
|
||||||
|
grantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");
|
||||||
|
|
||||||
public Collection<GrantedAuthority> convert(Jwt jwt) {
|
JwtAuthenticationConverter authenticationConverter = new JwtAuthenticationConverter();
|
||||||
Collection<?> authorities = (Collection<?>)
|
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(authoritiesConverter);
|
||||||
jwt.getClaims().getOrDefault("mycustomclaim", Collections.emptyList());
|
return jwtAuthenticationConverter;
|
||||||
|
|
||||||
return authorities.stream()
|
|
||||||
.map(Object::toString)
|
|
||||||
.map(SimpleGrantedAuthority::new)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
|
.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>`:
|
For more flexibility, the DSL supports entirely replacing the converter with any class that implements `Converter<Jwt, AbstractAuthenticationToken>`:
|
||||||
|
|
||||||
[source,java]
|
[source,java]
|
||||||
|
|
Loading…
Reference in New Issue