First of all, according to Spring doc , if i want to map user roles to scopes, i should use setCheckUserScopes(true) to DefaultOAuth2RequestFactory. So one way to do this, is injecting my own DefaultOAuth2RequestFactory bean, as doc says:
The AuthorizationServerEndpointsConfigurer allows you to inject a custom OAuth2RequestFactory so you can use that feature to set up a factory if you use @EnableAuthorizationServer.
Then i do
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends
AuthorizationServerConfigurerAdapter {
...
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints.authenticationManager(authenticationManager)
.tokenStore(tokenStore)
.tokenServices(tokenServices());
endpoints
.getOAuth2RequestFactory(); // this doesn't return me my own DefaultOAuth2RequestFactory
}
@Bean
@Primary
public OAuth2RequestFactory defaultOAuth2RequestFactory() {
DefaultOAuth2RequestFactory defaultOAuth2RequestFactory = new DefaultOAuth2RequestFactory(
clientDetailsService);
defaultOAuth2RequestFactory.setCheckUserScopes(true);
return defaultOAuth2RequestFactory;
}
}
I've overlooked the method requestFactory() from AuthorizationServerEndpointsConfigurer. That was the correct way to pass it to Spring Security. Setting OAuth2RequestFactory bean as primary didn't work. I've deleted some things to focus on the real problem:
After this observation, the actual problem:
as i understand, if the user has authorities A and B, and the app has scope A, then he gets just 'A' scope. But this is not happening. What is really happening is that if app has scope A, and APP (not user) has authorities A and B, then user gets A. But this doesn't make any sense. This is DefaultOAuth2RequestFactory method that resolve user's scopes:
private Set<String> extractScopes(Map<String, String> requestParameters, String clientId) {
... // I avoid some unimportant lines to not make this post so long
if ((scopes == null || scopes.isEmpty())) {
scopes = clientDetails.getScope();
}
if (checkUserScopes) {
scopes = checkUserScopes(scopes, clientDetails);
}
return scopes;
}
private Set<String> checkUserScopes(Set<String> scopes, ClientDetails clientDetails) {
if (!securityContextAccessor.isUser()) {
return scopes;
}
Set<String> result = new LinkedHashSet<String>();
Set<String> authorities = AuthorityUtils.authorityListToSet(securityContextAccessor.getAuthorities());
for (String scope : scopes) {
if (authorities.contains(scope) || authorities.contains(scope.toUpperCase())
|| authorities.contains("ROLE_" + scope.toUpperCase())) {
result.add(scope);
}
}
return result;
}
Is this a bug? Please tell me if i am wrong. Regards
You need to wire your OAuth2RequestFactory by code something like here.
If the authorities are set by ClientDetailsService then you should be good. If you are looking to map logged-in user authorities I don't have luck there either.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With