Is Spring Boot WebClient OAuth2 client_credentials supported?

≯℡__Kan透↙ 提交于 2020-05-14 12:06:59

问题


I'm trying to create a Spring Boot REST application that has to make a remote REST call to another Spring Boot application protected by OAuth2 (with grant type client_credentials).

The first application is using the Reactive WebClient to make the call to the second OAuth2 REST application.

I've configured the the WebClient with grant_type "client_credentials" (see code below)

public WebClient messageWebClient(
        ClientRegistrationRepository clientRegistrations,
        OAuth2AuthorizedClientRepository authorizedClients,
        ClientHttpConnector clientHttpConnector
) {

    ServletOAuth2AuthorizedClientExchangeFilterFunction oauth =
            new ServletOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations, authorizedClients);

    oauth.setDefaultClientRegistrationId("message");

    return WebClient.builder()
            .baseUrl(MESSAGE_BASE_URL)
            .clientConnector(clientHttpConnector)
            .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
            .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
            .filter(oauth)
            .filter(logRequest())
            .build();
}

@Bean
public ClientRegistrationRepository  clientRegistrations() {
    ClientRegistration clientRegistration = ClientRegistration
            .withRegistrationId("message")
            .clientId("client")
            .clientSecret("secret")
            .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
            .tokenUri("http://localhost:8081/oauth/token")
            .build();

    return new InMemoryClientRegistrationRepository(clientRegistration);
}

But every time I'm making a Postman call to the first application I end up with the following exception:

"IllegalArgumentException: Invalid Authorization Grant Type (client_credentials) for Client Registration with Id: ..." from the DefaultOAuth2AuthorizationRequestResolver

Is "client_credentials" really supported for WebClient... or am I missing something ?

Regards

  • First Application code: https://github.com/fdlessard/SpringBootOauth2WebClient
  • SecondApplication code: https://github.com/fdlessard/SpringBootOAuth2Message

  • SpringBoot Version 2.1.4

  • spring-security-oauth2-client: 5.1.5.RELEASE

回答1:


You have to use .apply(oauth.oauth2Configuration()) instead of .filter(oauth), see ServletOAuth2AuthorizedClientExchangeFilterFunction:

Provides an easy mechanism for using an OAuth2AuthorizedClient to make OAuth2 requests by including the token as a Bearer Token. It also provides mechanisms for looking up the OAuth2AuthorizedClient. This class is intended to be used in a servlet environment. Example usage:

OAuth2AuthorizedClientExchangeFilterFunction oauth2 = new OAuth2AuthorizedClientExchangeFilterFunction(authorizedClientService);
WebClient webClient = WebClient.builder()
    .apply(oauth2.oauth2Configuration())
    .build();
Mono response = webClient
    .get()
    .uri(uri)
    .attributes(oauth2AuthorizedClient(authorizedClient))
    // ...
    .retrieve()
    .bodyToMono(String.class);

and Spring Security Reference:

13.1 WebClient OAuth2 Setup

The first step is ensuring to setup the WebClient correctly. An example of setting up WebClient in a servlet environment can be found below:

@Bean
WebClient webClient(ClientRegistrationRepository clientRegistrations,
        OAuth2AuthorizedClientRepository authorizedClients) {
    ServletOAuth2AuthorizedClientExchangeFilterFunction oauth =
            new ServletOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations, authorizedClients);
    // (optional) explicitly opt into using the oauth2Login to provide an access token implicitly
    // oauth.setDefaultOAuth2AuthorizedClient(true);
    // (optional) set a default ClientRegistration.registrationId
    // oauth.setDefaultClientRegistrationId("client-registration-id");
    return WebClient.builder()
            .apply(oauth2.oauth2Configuration())
            .build();
}



回答2:


Well, I was finally able to make my code work.

... and yes, the WebClient does support OAuth2 with client_credential (well partially).

To solve my problems I had to disable oauth2 auto configuration and create my own implementation of WebSecurityConfigurerAdapter.

The reason I say "partially" is because the current version of spring security (5.1.x) for WebClient does not ask for a new token once the token expires (for client credential). Only with version 5.2.0.M2 or (M1) it ask for a new token when the token is expired.

Thank you :)



来源:https://stackoverflow.com/questions/55894460/is-spring-boot-webclient-oauth2-client-credentials-supported

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!