问题
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 theOAuth2AuthorizedClient
. 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