| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 | 
							- = WebClient
 
- [NOTE]
 
- ====
 
- The following documentation is for use within Reactive environments.
 
- For Servlet environments, refer to xref:servlet/oauth2/oauth2-client.adoc#oauth2Client-webclient-servlet[ WebClient for Servlet] environments.
 
- ====
 
- Spring Framework has built in support for setting a Bearer token.
 
- ====
 
- .Java
 
- [source,java,role="primary"]
 
- ----
 
- webClient.get()
 
-     .headers(h -> h.setBearerAuth(token))
 
-     ...
 
- ----
 
- .Kotlin
 
- [source,kotlin,role="secondary"]
 
- ----
 
- webClient.get()
 
-     .headers { it.setBearerAuth(token) }
 
-     ...
 
- ----
 
- ====
 
- Spring Security builds on this support to provide additional benefits:
 
- * Spring Security will automatically refresh expired tokens (if a refresh token is present)
 
- * If an access token is requested and not present, Spring Security will automatically request the access token.
 
- ** For authorization_code this involves performing the redirect and then replaying the original request
 
- ** For client_credentials the token is simply requested and saved
 
- * Support for the ability to transparently include the current OAuth token or explicitly select which token should be used.
 
- [[webclient-setup]]
 
- == WebClient OAuth2 Setup
 
- The first step is ensuring to setup the `WebClient` correctly.
 
- An example of setting up `WebClient` in a fully reactive environment can be found below:
 
- ====
 
- .Java
 
- [source,java,role="primary"]
 
- ----
 
- @Bean
 
- WebClient webClient(ReactiveClientRegistrationRepository clientRegistrations,
 
- 		ServerOAuth2AuthorizedClientRepository authorizedClients) {
 
- 	ServerOAuth2AuthorizedClientExchangeFilterFunction oauth =
 
- 			new ServerOAuth2AuthorizedClientExchangeFilterFunction(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()
 
- 			.filter(oauth)
 
- 			.build();
 
- }
 
- ----
 
- .Kotlin
 
- [source,kotlin,role="secondary"]
 
- ----
 
- @Bean
 
- fun webClient(clientRegistrations: ReactiveClientRegistrationRepository,
 
-               authorizedClients: ServerOAuth2AuthorizedClientRepository): WebClient {
 
-     val oauth = ServerOAuth2AuthorizedClientExchangeFilterFunction(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()
 
-             .filter(oauth)
 
-             .build()
 
- }
 
- ----
 
- ====
 
- [[webclient-implicit]]
 
- == Implicit OAuth2AuthorizedClient
 
- If we set `defaultOAuth2AuthorizedClient` to `true` in our setup and the user authenticated with oauth2Login (i.e. OIDC), then the current authentication is used to automatically provide the access token.
 
- Alternatively,  if we set `defaultClientRegistrationId` to a valid `ClientRegistration` id, that registration is used to provide the access token.
 
- This is convenient, but in environments where not all endpoints should get the access token, it is dangerous (you might provide the wrong access token to an endpoint).
 
- ====
 
- .Java
 
- [source,java,role="primary"]
 
- ----
 
- Mono<String> body = this.webClient
 
- 		.get()
 
- 		.uri(this.uri)
 
- 		.retrieve()
 
- 		.bodyToMono(String.class);
 
- ----
 
- .Kotlin
 
- [source,kotlin,role="secondary"]
 
- ----
 
- val body: Mono<String> = webClient
 
-         .get()
 
-         .uri(this.uri)
 
-         .retrieve()
 
-         .bodyToMono()
 
- ----
 
- ====
 
- [[webclient-explicit]]
 
- == Explicit OAuth2AuthorizedClient
 
- The `OAuth2AuthorizedClient` can be explicitly provided by setting it on the requests attributes.
 
- In the example below we resolve the `OAuth2AuthorizedClient` using Spring WebFlux or Spring MVC argument resolver support.
 
- However, it does not matter how the `OAuth2AuthorizedClient` is resolved.
 
- ====
 
- .Java
 
- [source,java,role="primary"]
 
- ----
 
- @GetMapping("/explicit")
 
- Mono<String> explicit(@RegisteredOAuth2AuthorizedClient("client-id") OAuth2AuthorizedClient authorizedClient) {
 
- 	return this.webClient
 
- 			.get()
 
- 			.uri(this.uri)
 
- 			.attributes(oauth2AuthorizedClient(authorizedClient))
 
- 			.retrieve()
 
- 			.bodyToMono(String.class);
 
- }
 
- ----
 
- .Kotlin
 
- [source,kotlin,role="secondary"]
 
- ----
 
- @GetMapping("/explicit")
 
- fun explicit(@RegisteredOAuth2AuthorizedClient("client-id") authorizedClient: OAuth2AuthorizedClient?): Mono<String> {
 
-     return this.webClient
 
-             .get()
 
-             .uri(uri)
 
-             .attributes(oauth2AuthorizedClient(authorizedClient))
 
-             .retrieve()
 
-             .bodyToMono()
 
- }
 
- ----
 
- ====
 
- [[webclient-clientregistrationid]]
 
- == clientRegistrationId
 
- Alternatively, it is possible to specify the `clientRegistrationId` on the request attributes and the `WebClient` will attempt to lookup the `OAuth2AuthorizedClient`.
 
- If it is not found, one will automatically be acquired.
 
- ====
 
- .Java
 
- [source,java,role="primary"]
 
- ----
 
- Mono<String> body = this.webClient
 
- 		.get()
 
- 		.uri(this.uri)
 
- 		.attributes(clientRegistrationId("client-id"))
 
- 		.retrieve()
 
- 		.bodyToMono(String.class);
 
- ----
 
- .Kotlin
 
- [source,kotlin,role="secondary"]
 
- ----
 
- val body: Mono<String> = this.webClient
 
-         .get()
 
-         .uri(uri)
 
-         .attributes(clientRegistrationId("client-id"))
 
-         .retrieve()
 
-         .bodyToMono()
 
- ----
 
- ====
 
 
  |