I have a Spring Authorization Server 1.2.0 project where I have access to a RegisteredClient
that has scopes profile
and read.custom.scope
. This client has grant types refresh_token
and authorization_code
. The authorizations are being persisted to the DB with appropriate repositories etc.
Up until recently I had no need for scopes in the token. When going to use them I realised the token doesn’t have authorized scopes.
To remedy this I configured an OAuth2TokenCustomizer to add the consented scopes to the token as an authorities claim.
@Bean
public OAuth2TokenCustomizer<JwtEncodingContext> oAuth2TokenCustomizer() {
return context -> {
OAuth2Authorization oAuth2Authorization = context.getAuthorization();
context.getClaims().claim( "authorities", oAuth2Authorization.getAuthorizedScopes() );
};
}
However, this did not work as the oAuth2Authorization.getAuthorizedScopes()
returns an empty Collection. I now see an empty array of authorities in the accessToken.
I have checked that my RegisteredClient has the correct scopes and ensured that conversion between RegisteredClient -> ClientEntity and ClientEntity -> RegisteredClient hasn’t lost this scope information along the way.
The persisted authorization entry also has an empty value for the accessTokenScopes
property.
I’m able to debug the OAuth2AuthorizationEndpointFilter
and can see that the authentication
object in the filter has the correct scopes I’d expect to see.
I have a JwtDecoder that I use for an external inbond mechanisim for authentication (rather than using formLogin):
@Bean
@Order(2)
public SecurityFilterChain standardSecurityFilterChain(HttpSecurity http) throws Exception {
...
.oauth2ResourceServer(configurer -> {
configurer.jwt(jwtConfigurer -> jwtConfigurer.decoder( ssoAuthenticationJwtDecoder() ));
});
http.csrf().disable();
return http.build();
}
@Bean(name = "jwtDecoder")
public JwtDecoder ssoAuthenticationJwtDecoder() {
return new CustomJwtDecoder();
}
I then have a JwtDecoder that’s used for the OAuth Authorization Server:
@Bean
public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
}
I’m not sure the JWT decoder stuff is the issue here but it’s weird so thought I’d include it for context.
The big question: How can I ensure that the consented scopes become authorizedScopes that will be available when I call context.getAuthorizedScopes()
?
Any and all pointers and help greatly welcome.