Expected Behavior
Our current OAuth2 provider returns a custom claim for the roles, which I would like to convert.
Currently I cannot override the method here https://github.com/spring-projects/spring-security/blob/main/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/introspection/NimbusOpaqueTokenIntrospector.java#L212 because the convert method is private.
Could this method be made protected or public or offer other alternatives to convert custom claims?
Current Behavior
Everything is private for the NimbusOpaqueTokenIntrospector so i have no chance to convert custom claims.
Context
Example what I we currently need to convert roles
private Collection<GrantedAuthority> getAuthorities( final TokenIntrospectionSuccessResponse response, final Map<String, Object> claims ) {
final Collection<GrantedAuthority> authorities = new ArrayList<>();
if ( response.getScope() != null ) {
final List<String> scopes = Collections.unmodifiableList( response.getScope().toStringList() );
claims.put( SCOPE, scopes );
for ( final String scope : scopes ) {
authorities.add( new SimpleGrantedAuthority( authorityPrefix + scope ) );
}
}
final List<String> roles = response.getStringListParameter( roleClaim );
if ( !CollectionUtils.isEmpty( roles ) ) {
claims.put( roleClaim, roles );
roles.forEach( role -> authorities.add( new SimpleGrantedAuthority( rolePrefix + role ) ) );
}
return authorities;
}
Comment From: jzheaux
Hi, @MelleD, thanks for the suggestion. As a side note, unless you need something Nimbus-specific, I'd recommend using SpringOpaqueTokenIntrospector.
And, in light of that, yes, I think it is reasonable to add a setter like this one to SpringOpaqueTokenIntrospector:
public void setAuthenticationConverter(Converter<OAuth2TokenIntrospectionClaimAccessor, OAuth2AuthenticatedPrincipal> converter)
SpringOpaqueTokenIntrospector would convert the claim set and then call this converter.
Then, your configuration would look something like:
@Bean
OpaqueTokenIntrospector opaqueTokenIntrospector() {
SpringOpaqueTokenIntrospector introspector = new SpringOpaqueTokenIntrospector();
introspector.setAuthenticationConverter((accessor) -> {
List<String> scopes = accessor.getScopes();
// ... convert into authorities as needed
return new OAuth2IntrospectionAuthenticatedPrincipal(accessor.getClaims(), authorities);
});
return introspector;
}
In this way, if folks need to do any further customization on the principal, they can do that as well in the same converter.
Are you able to provide a PR that makes these changes?
Comment From: MelleD
@jzheaux
thanks for the quick reply. Let me double check the code. I was not aware of the SpringOpaqueTokenIntrospector.
I'll check whether we need more customization.
Is there also the possibility of simply setting the converter as a bean without creating the SpringOpaqueTokenIntrospector?
Comment From: jzheaux
Perhaps in time, @MelleD. I prefer to move a bit slowly on that front given that publishing the OpaqueTokenIntrospector is already simple. Generally speaking, Spring Security picks up beans that are either cross-cutting in nature (like SecurityContextHolderStrategy) or map to a specific HttpSecurity DSL method (like OpaqueTokenIntrospector/.introspector()).
Comment From: MelleD
@ahmd-nabil thanks :).