Spring OAuth2 checkUserScopes未按预期工作

时间:2015-07-13 19:15:41

标签: java spring authentication user-permissions spring-security-oauth2

首先,根据Spring doc ,如果我想将用户角色映射到范围,我应该使用setCheckUserScopes(true)到DefaultOAuth2RequestFactory。因此,一种方法是注入我自己的DefaultOAuth2RequestFactory bean,正如doc所说:

The AuthorizationServerEndpointsConfigurer allows you to inject a custom OAuth2RequestFactory so you can use that feature to set up a factory if you use @EnableAuthorizationServer.

然后我做

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

修改

我忽略了AuthorizationServerEndpointsConfigurer中的方法requestFactory()。这是将它传递给Spring Security的正确方法。将OAuth2RequestFactory bean设置为主要功能并不起作用。我删除了一些关注真正问题的事情:

经过这次观察,实际问题:

据我了解,如果用户有权限A和B,并且应用程序具有范围A,那么他只会得到A' A'范围。但这不会发生。真正发生的是,如果app具有范围A,而APP(非用户)具有权限A和B,则用户获得A.但这没有任何意义。 这是解决用户范围的DefaultOAuth2RequestFactory方法:

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

这是一个错误吗?请告诉我,如果我错了。此致

2 个答案:

答案 0 :(得分:3)

您需要使用代码like here连接您的OAuth2RequestFactory。

如果当局由ClientDetailsService设定,那么你应该是好人。如果您要映射登录的用户权限don't have luck there either

答案 1 :(得分:0)

我也在努力寻找解决方案 如果您希望使用用户的授予权限或令牌中的任何自定义属性,可以进行解决,以检查资源服务器中请求资源的权限,然后可以执行以下操作

public class CustomAuthoritiesClaimName extends WebSecurityConfigurerAdapter {
    protected void configure(HttpSecurity http) {
        http
            .authorizeRequests(authorize -> authorize
                .anyRequest().authenticated()
            )
            .oauth2ResourceServer(oauth2 -> oauth2
                .jwt(jwt -> jwt
                    .jwtAuthenticationConverter(jwtAuthenticationConverter())
                )
            );
    }
}

JwtAuthenticationConverter jwtAuthenticationConverter() {
    JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
    grantedAuthoritiesConverter.setAuthoritiesClaimName("authorities");

    JwtAuthenticationConverter authenticationConverter = new JwtAuthenticationConverter();
    jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(authoritiesConverter);
    return jwtAuthenticationConverter;
}

但是您将必须授予与用户权限相同的范围,这也可以通过实现 Ouath2RequestFactory btw idk来解决。here您可以看到他拥有提到了