it-swarm.com.de

Warum wird mein Token abgelehnt? Was ist eine Ressourcen-ID? "Ungültiges Token enthält keine Ressourcen-ID (oauth2-resource)"

Ich versuche, OAuth2 für ein Frühjahrsprojekt zu konfigurieren. Ich verwende eine gemeinsam genutzte UAA ( oauth-Implementierung von Cloud Foundry ), die mein Arbeitsplatz bereitstellt (ich versuche also nicht, einen Autorisierungsserver zu erstellen, und der Autorisierungsserver ist vom Ressourcenserver getrennt). Das Frontend ist eine Single-Page-Anwendung, die mithilfe der impliziten Erteilung Token direkt vom Autorisierungsserver erhält. Ich habe das SPA-Setup, in dem der Authorization: Bearer <TOKEN>-Header bei jedem Web-API-Aufruf zu Microservices hinzugefügt wird.

Mein Problem ist jetzt bei den Microservices.

Ich versuche, diesen freigegebenen Autorisierungsserver zum Authentifizieren der Mikrodienste zu verwenden. Ich könnte hier ein Missverständnis haben. Meines Wissens ist es so, dass diese Mikrodienste die Rolle des Ressourcenservers spielen, da sie die Endpunkte hosten, die der SPA zum Abrufen von Daten verwendet.

Also habe ich versucht, einen Microservice so zu konfigurieren:

@Configuration
@EnableResourceServer
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
        .authorizeRequests()
        .antMatchers("/api/**").authenticated();
    }

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

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setVerifierKey("-----BEGIN PUBLIC KEY-----<key omitted>-----END PUBLIC KEY-----");
        return converter;
    }

    @Bean
    @Primary
    public DefaultTokenServices tokenServices() {
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(tokenStore());
        return defaultTokenServices;
    }


    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
         resources.tokenServices(tokenServices());
    }
}

Immer wenn ich einen /api/** mit dem Authorization: Bearer <TOKEN> treffe, erhalte ich einen 403 mit dieser Fehlermeldung:

{
    "error": "access_denied",
    "error_description": "Invalid token does not contain resource id (oauth2-resource)"
}

Also hier sind meine Fragen:

  • Wie konfiguriere ich diese Mikrodienste, um das Token zu validieren und eine Principal in Controller-Methoden einzufügen? Ich habe es derzeit eingerichtet, wo der SPA verfügt und das Token sendet, und ich habe auch den öffentlichen Schlüssel, mit dem die Signatur des Tokens überprüft wird. Ich habe auch jwt.io verwendet, um das Token zu testen, und es wird "Signatur verifiziert" angezeigt.
  • Was ist eine Ressourcennummer? Warum brauche ich es und warum verursacht es den obigen Fehler? Ist das nur ein Frühling?

Vielen Dank!

5
Rico Kahler

Spring OAuth erwartet "aud" claim in JWT-Token. Der Wert dieses Anspruchs sollte mit dem resourceId-Wert übereinstimmen, den Sie für Ihre Spring-App angeben (falls nicht angegeben, wird standardmäßig "oauth2-resource" verwendet).

Um Ihr Problem zu beheben, müssen Sie:

1) Melden Sie sich bei Ihrer gemeinsam genutzten UAA an und vergewissern Sie sich, dass die Angabe "aud" enthalten ist.

2) Ändern Sie den Wert dieses Anspruchs "aud" als "oauth2-resource" oder vorzugsweise in Ihrer Spring-App-Aktualisierung resourceId in den Wert dieses Anspruchs wie folgt:

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
         resources.tokenServices(tokenServices());
         resources.resourceId(value from the aud claim you got from UAA server);
    }
11
tsolakp

Ich füge eine ähnliche Ausgabe hinzu. In meinem Fall habe ich die Jdbc-Authentifizierung verwendet, und mein Autorisierungsserver und Ressourcenserver bestand aus zwei separaten APIs.

  • Authentifizierungsserver

       @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
    oauthServer.tokenKeyAccess("permitAll()")
                .checkTokenAccess("isAuthenticated()")
                .passwordEncoder(oauthClientPasswordEncoder);
    

    }

    /**
    * Define the client details service. The client may be define either as in memory or in database.
     * Here client with be fetch from the specify database
      */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
       clients.jdbc(dataSource);
    }
    
    /**
    * Define the authorization by providing authentificationManager
    * And the token enhancement
     */
     @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
    endpoints.tokenStore(tokenStore())
                .tokenEnhancer(getTokenEnhancer())
                .authenticationManager(authenticationManager).userDetailsService(userDetailsService);
     }
    
  • Ressourcenserver

    public class OAuth2ResourceServerConfig extends 
        ResourceServerConfigurerAdapter {
    
        private TokenExtractor tokenExtractor = new BearerTokenExtractor();
    
        @Autowired
        private DataSource dataSource;
    
        @Bean
        public TokenStore tokenStore() {
          return new JdbcTokenStore(dataSource);
        }
    
         @Override
         public void configure(HttpSecurity http) throws Exception {
               http.addFilterAfter(new OncePerRequestFilter() {
               @Override
               protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                FilterChain filterChain) throws ServletException, IOException {
            // We don't want to allow access to a resource with no token so clear
            // the security context in case it is actually an OAuth2Authentication
            if (tokenExtractor.extract(request) == null) {
                SecurityContextHolder.clearContext();
            }
            filterChain.doFilter(request, response);
        }
    }, AbstractPreAuthenticatedProcessingFilter.class);
    http.csrf().disable();
    http.authorizeRequests().anyRequest().authenticated();
     }
    
      @Bean
      public AccessTokenConverter accessTokenConverter() {
         return new DefaultAccessTokenConverter();
      }
    
      @Bean
      public RemoteTokenServices remoteTokenServices(final @Value("${auth.server.url}") String checkTokenUrl,
        final @Value("${auth.resource.server.clientId}") String clientId,
        final @Value("${auth.resource.server.clientsecret}") String clientSecret) {
    
           final RemoteTokenServices remoteTokenServices = new RemoteTokenServices();
           remoteTokenServices.setCheckTokenEndpointUrl(checkTokenUrl);
           remoteTokenServices.setClientId(clientId);
           remoteTokenServices.setClientSecret(clientSecret);
          remoteTokenServices.setAccessTokenConverter(accessTokenConverter());
    return remoteTokenServices;
       }
    

Mit dieser Konfiguration bekam ich

    {
       "error": "access_denied",
       "error_description": "Invalid token does not contain resource id 
       (xxxxx)"
     }

Um das zu lösen, musste ich hinzufügen

    private String resourceIds= "xxxxx". !! maked sure that this resourceids is store in oauth_client_details for the clientid I used to get the token
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
          resources.resourceId(resourceIds).tokenStore(tokenStore());
      }
1
onlyme