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;
}
}
EDIT
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