Wie konfiguriere ich Resource Server in Spring Security für die Verwendung zusätzlicher Informationen im JWT-Token?

Ich habe einen oauth2-JWT-Tokenserver konfiguriert, um zusätzliche Informationen zu den Benutzerberechtigungen festzulegen.

@Configuration
@Component
public class CustomTokenEnhancer extends JwtAccessTokenConverter {

    CustomTokenEnhancer(){
        super();
    }

    @Override
    public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
        // TODO Auto-generated method stub
        MyUserDetails user = (MyUserDetails) authentication.getPrincipal();
        final Map<String, Object> additionalInfo = new HashMap<>();
        @SuppressWarnings("unchecked")
        List<GrantedAuthority> authorities= (List<GrantedAuthority>) user.getAuthorities();
        additionalInfo.put("authorities", authorities);

        ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);

        return accessToken;
    }

}

Ich bin nicht sicher, wie ich meinen Ressourcenserver so konfigurieren soll, dass die vom oauth2-Server festgelegten Benutzerberechtigungen extrahiert werden und diese Berechtigung für mit @Secured annotierte Controller in Spring Security Framework verwendet wird.

Meine Auth-Serverkonfiguration sieht folgendermaßen aus:

@Configuration
@EnableAuthorizationServer
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {

    @Value("${config.oauth2.privateKey}")
    private String privateKey;

    @Value("${config.oauth2.publicKey}")
    private String publicKey;

    @Value("{config.clienturl}")
    private String clientUrl;

    @Autowired
    AuthenticationManager authenticationManager;

    @Bean
    public JwtAccessTokenConverter customTokenEnhancer(){

        JwtAccessTokenConverter customTokenEnhancer = new CustomTokenEnhancer();
        customTokenEnhancer.setSigningKey(privateKey);

        return customTokenEnhancer;
    }

    @Bean
    public JwtTokenStore tokenStore() {
        return new JwtTokenStore(customTokenEnhancer());
    }


    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer
                .tokenKeyAccess("isAnonymous() || hasRole('ROLE_TRUSTED_CLIENT')") // permitAll()
                .checkTokenAccess("hasRole('TRUSTED_CLIENT')"); // isAuthenticated()
    }


    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints


        .authenticationManager(authenticationManager)
        .tokenStore(tokenStore())
        .accessTokenConverter(customTokenEnhancer())
;
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

        String url = clientUrl;

        clients.inMemory()


        .withClient("public") 
        .authorizedGrantTypes("client_credentials", "implicit")
        .scopes("read")
        .redirectUris(url)

        .and()


        .withClient("eagree_web").secret("eagree_web_dev")
        //eagree_web should come from properties file?
        .authorities("ROLE_TRUSTED_CLIENT") 
        .authorizedGrantTypes("client_credentials", "password", "authorization_code", "refresh_token")
        .scopes("read", "write", "trust") 
        .redirectUris(url).resourceIds("dummy");
    }
}

Und meine Resource Server-Konfiguration sieht folgendermaßen aus:

@Configuration
@EnableResourceServer
public class ResourceServerConfiguration  extends ResourceServerConfigurerAdapter {



    @Value("{config.oauth2.publicKey}")
    private String publicKey;

    @Autowired
    CustomTokenEnhancer tokenConverter;

    @Autowired
    JwtTokenStore jwtTokenStore;

    @Bean
    public JwtTokenStore jwtTokenStore() {
        tokenConverter.setVerifierKey(publicKey);
        jwtTokenStore.setTokenEnhancer(tokenConverter);
        return jwtTokenStore;
    }

    @Bean
    public ResourceServerTokenServices defaultTokenServices() {
        final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenEnhancer(tokenConverter);
        defaultTokenServices.setTokenStore(jwtTokenStore());
        return defaultTokenServices;
    }


    @Override
    public void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        // @formatter:off
        http
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER)
                .and()
                .requestMatchers()
                .antMatchers("/**")
                .and()
                .authorizeRequests()
                .antMatchers(HttpMethod.OPTIONS, "/api/**").permitAll()
                .antMatchers(HttpMethod.GET, "/api/**").access("#oauth2.hasScope('read')")
                .antMatchers(HttpMethod.PATCH, "/api/**").access("#oauth2.hasScope('write')")
                .antMatchers(HttpMethod.POST, "/api/**").access("#oauth2.hasScope('write')")
                .antMatchers(HttpMethod.PUT, "/api/**").access("#oauth2.hasScope('write')")
                .antMatchers(HttpMethod.DELETE, "/api/**").access("#oauth2.hasScope('write')")
                .antMatchers("/admin/**").access("hasRole('ROLE_USER')");

        // @formatter:on
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        System.out.println("Configuring ResourceServerSecurityConfigurer ");
        resources.resourceId("dummy").tokenServices(defaultTokenServices());
    }

}

Mein Testfall scheitert kläglich und sagt:

{"error": "invalid_token", "error_description": "Zugriffstoken kann nicht in JSON konvertiert werden"}

Wie erhalte ich das Authentifizierungsobjekt aus dem JWT? Wie authentifiziere ich den Client mit Clientanmeldeinformationen? Wie verwende ich @Secured Annotation auf meinen Ressourcencontrollern?

Welcher Code wird auf der Seite des Ressourcenservers verwendet, um das Token zu dekodieren, um Clientanmeldeinformationen zu extrahieren, und welcher Code wird für die Benutzerrolle überprüft?

Bitte hilf mir, da ich bereits 2 Tage damit verbracht habe, meinen Kopf auf diese scheinbar einfache Aufgabe zu stoßen.

Hinweis: Ich erhalte das Token vom Authentifizierungsserver als: {access_token = b5d89a13-3c8b-4bda-b0f2-a6e9d7b7a285, token_type = bearer, refresh_token = 43777224-b6f2-44d7-bf36-4e1934d32cb , authority = [{authority = ROLE_USER}, {authority = ROLE_ADMIN}]}

Bitte erläutern Sie die Konzepte und weisen Sie darauf hin, wenn in meiner Konfiguration etwas fehlt. Ich muss die Best Practices für die Konfiguration meiner Ressource und meines Authentifizierungsservers kennen.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage