web-dev-qa-db-fra.com

Feign et Spring Security 5 - Critiques du client

J'essaie d'invoquer un système de backend sécurisé par un type de subvention client_credentials à partir d'une application client Feign.

Le jeton d'accès du système de backend peut être récupéré avec la structure de boucle suivante (tout comme exemple):

curl --location --request POST '[SERVER URL]/oauth/grant' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Cookie: WebSessionID=172.22.72.1.1558614080219404; b8d49fdc74b7190aacd4ac9b22e85db8=2f0e4c4dbf6d4269fd3349f61c151223' \
--data-raw 'grant_type=client_credentials' \
--data-raw 'client_id=[CLIENT_ID]' \
--data-raw 'client_secret=[CLIENT_SECRET]'

{"accessToken":"V29C90D1917528E9C29795EF52EC2462D091F9DC106FAFD829D0FA537B78147E20","tokenType":"Bearer","expiresSeconds":7200}

Cet accèsPRoken doit ensuite être défini dans un en-tête pour les appels commerciaux ultérieurs au système Backend.

Alors maintenant, ma question est de savoir comment mettre en œuvre cette utilisation en utilisant une sécurité de démarrage Feign et Spring 5. Après quelques recherches, je viens à cette solution (qui ne fonctionne pas):

  1. Définissez mon client dans l'application.yml:
spring:
  security:
    oauth2:
      client:
        registration:
          backend:
            client-id:[CLIENT_ID]
            client-secret: [CLIENT_SECRET]
            authorization-grant-type: client_credentials
    
        provider:
          backend:
            token-uri: [SERVER URL]/oauth/grant
  1. Créez un bean Oauth2AuthorizeClientManager pour pouvoir autoriser (ou ré-autoriser) AN OAuth 2.0 Client:
@Bean
public OAuth2AuthorizedClientManager authorizedClientManager(
        ClientRegistrationRepository clientRegistrationRepository,
        OAuth2AuthorizedClientRepository authorizedClientRepository) {

    DefaultOAuth2AuthorizedClientManager authorizedClientManager =
            new DefaultOAuth2AuthorizedClientManager(
                    clientRegistrationRepository, authorizedClientRepository);

    return authorizedClientManager;
}
  1. Créez un intercepteur de requête Feign qui utilise l'Oauth2authorizeClientManager:
public class OAuthRequestInterceptor implements RequestInterceptor {

    private OAuth2AuthorizedClientManager manager;

    public OAuthRequestInterceptor(OAuth2AuthorizedClientManager manager) {
        this.manager = manager;
    }

    @Override
    public void apply(RequestTemplate requestTemplate) {
        OAuth2AuthorizedClient client = this.manager.authorize(OAuth2AuthorizeRequest.withClientRegistrationId("backend").principal(createPrincipal()).build());
        String accessToken = client.getAccessToken().getTokenValue();
        requestTemplate.header(HttpHeaders.AUTHORIZATION, "Bearer" + accessToken);
    }

    private Authentication createPrincipal() {
        return new Authentication() {
            @Override
            public Collection<? extends GrantedAuthority> getAuthorities() {
                return Collections.emptySet();
            }

            @Override
            public Object getCredentials() {
                return null;
            }

            @Override
            public Object getDetails() {
                return null;
            }

            @Override
            public Object getPrincipal() {
                return this;
            }

            @Override
            public boolean isAuthenticated() {
                return false;
            }

            @Override
            public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
            }

            @Override
            public String getName() {
                return "backend";
            }
        };
    }
}
  1. Créez un FEIGNCONFIG qui utilise l'intercepteur:
public class FeignClientConfig {


    @Bean
    public OAuthRequestInterceptor repositoryClientOAuth2Interceptor(OAuth2AuthorizedClientManager manager) {
        return new OAuthRequestInterceptor(manager);
    }
}
  1. Et c'est mon client Feign:
@FeignClient(name = "BackendRepository", configuration = FeignClientConfig.class, url = "${BACKEND_URL}")
public interface BackendRepository {

    @GetMapping(path = "/healthChecks", produces = MediaType.APPLICATION_JSON_VALUE)
    public Info healthCheck();
}

Lors de l'exécution de ce code, j'obtiens l'erreur:

org.springframework.web.client.UnknownContentTypeException: Could not extract response: no suitable HttpMessageConverter found for response type [class org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse] and content type [text/html;charset=utf-8]

Débogage du code Il ressemble à la défaillanceClientCredentialSokeSecLIent demande le point d'extrémité d'authentification à l'aide de l'authentification de base. Bien que je ne monte jamais ça.

Toute conseille ce que je peux faire? Peut-être qu'il y a une approche complètement différente pour faire cela.

9
Ralf

J'ai essayé votre approche. Malheureusement sans succès. Mais celui-ci a travaillé pour moi: Spring Cloud Feign Oauth2 Demander Interceptor ne fonctionne pas . On dirait que j'utilise beaucoup de déprédations maintenant, mais au moins cela fonctionne.

0
hilbert