Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring OAuth2 checkUserScopes is not working as expected

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

like image 712
jscherman Avatar asked Jul 13 '15 19:07

jscherman


1 Answers

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.

like image 86
Stackee007 Avatar answered Sep 23 '22 06:09

Stackee007