Сопоставление ролей пользователей с oauth2 областями/полномочиями

У нас есть база данных прав, в которой есть идентификатор, роли и пользователи приложения, сопоставленные с ролями для каждого приложения. Следуя советам в потоке, как мне сопоставить роли пользователей с oauth2 областями/полномочиями на основе resourceId?

Игнорируя базу данных прав, о которой я упоминал выше, сопоставляю ли вы роли "ПОЛЬЗОВАТЕЛЬ", "ЧИТАТЕЛЬ", "ПИСАТЕЛЬ" с oauth2 областями/полномочиями на основе user и resourceId ниже кода?

Конфигурация аутентификации пользователя/авторизации

@Configuration
@Order(-10)
protected static class LoginConfig extends WebSecurityConfigurerAdapter {

    ....

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // auth.parentAuthenticationManager(authenticationManager);
        // @formatter:off
        auth.inMemoryAuthentication()
            .withUser("admin").password("admin")
                .roles("ADMIN", "USER", "READER", "WRITER")
            .and()
            .withUser("user").password("password")
                .roles("USER")
            .and()
            .withUser("audit").password("audit")
                .roles("USER", "ADMIN", "READER");
        // @formatter:on
    }
}

Конфигурация OAuth2

@Configuration
@EnableAuthorizationServer
protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        // @formatter:off
        clients.inMemory()
            .withClient("acme").secret("acmesecret")
                .authorizedGrantTypes("authorization_code", "refresh_token", "password")
                .scopes("openid")
            .and()
            .withClient("trusted").secret("shuush")
                .authorizedGrantTypes("client_credentials")
                .scopes("openid");
        // @formatter:on
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager);
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.checkTokenAccess("isAuthenticated()");
    }
}

Обновление 1:

Введено в конфигурацию OAuth2RequestFactory, чтобы установить checkUserScopes в true. Хотя эта настройка работает для "client_credentails", она не подходит для "кодовых" грантов. Для "кодовых" грантов DefaultOAuth2RequestFactory пытается отображает полномочия для клиента (acme), а не пользователя на этапе авторизации. Другая мысль заключается в реализации ClientDetailsService, которые добавляют полномочия клиента (acme) на основе зарегистрированного пользователя (администратора/пользователя), но не конечно, как захватить зарегистрированного пользователя из SecurityContext, поскольку он перезаписывается клиентом (acme) на этапе авторизации. Любые идеи?

public class ScopeMappingOAuth2RequestFactory extends DefaultOAuth2RequestFactory {

    private SecurityContextAccessor securityContextAccessor = new DefaultSecurityContextAccessor();

    public ScopeMappingOAuth2RequestFactory(ClientDetailsService clientDetailsService) {
        super(clientDetailsService);
        super.setCheckUserScopes(true);
    }

    /**
     * @param securityContextAccessor the security context accessor to set
     */
    @Override
    public void setSecurityContextAccessor(SecurityContextAccessor securityContextAccessor) {
        this.securityContextAccessor = securityContextAccessor;
        super.setSecurityContextAccessor(securityContextAccessor);
    }

    @Override
    public AuthorizationRequest createAuthorizationRequest(Map<String, String> authorizationParameters) {
        AuthorizationRequest request = super.createAuthorizationRequest(authorizationParameters);

        if (securityContextAccessor.isUser()) {
            request.setAuthorities(securityContextAccessor.getAuthorities());
        }

        return request;
    }

}

и обновленный связанный код

@EnableAuthorizationServer
protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    private InMemoryClientDetailsService clientDetailsService;

    private Map<String, ClientDetails> clientDetailsStore;

    public InMemoryClientDetailsService clientDetailsService() {
        if (clientDetailsService == null) {
            clientDetailsStore = new HashMap<String, ClientDetails>();
            InMemoryClientDetailsService m = new InMemoryClientDetailsService() {

                @Override
                public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {
                    ClientDetails details = clientDetailsStore.get(clientId);
                    if (details == null) {
                        throw new NoSuchClientException("No client with requested id: " + clientId);
                    }
                    return details;
                }

            };
            clientDetailsService = m;
        }
        return clientDetailsService;
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        InMemoryClientDetailsServiceBuilder builder = new InMemoryClientDetailsServiceBuilder() {

            @Override
            protected void addClient(String clientId, ClientDetails value) {
                clientDetailsStore.put(clientId, value);
            }

            @Override
            protected ClientDetailsService performBuild() {
                return clientDetailsService();
            }
        };
        clients.setBuilder(builder);

        // @formatter:off
        builder
            .withClient("acme").secret("acmesecret")
                .authorizedGrantTypes("authorization_code", "refresh_token", "password")
                .scopes("openid", "apim.read", "apim.write")
            .and()
            .withClient("trusted").secret("shuush")
                .authorizedGrantTypes("client_credentials")
                .scopes("openid", "apim.read", "apim.write")
                .authorities("openid", "apim.read", "apim.write");
        // @formatter:on
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager);
        endpoints.requestFactory(new ScopeMappingOAuth2RequestFactory(clientDetailsService()));
    }

...   }

LoginConfig

Configuration
@Order(-10)
protected static class LoginConfig extends WebSecurityConfigurerAdapter {

....

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // auth.parentAuthenticationManager(authenticationManager);
        // @formatter:off
        auth.inMemoryAuthentication()
            .withUser("admin").password("admin")
                .roles("APIM.READ", "APIM.WRITE")
            .and()
            .withUser("user").password("password")
                .roles("APIM.READ")
            .and()
            .withUser("audit").password("audit")
                .roles("APIM.READ");
        // @formatter:on
    }
}

Ответы