|  | @@ -1,175 +0,0 @@
 | 
	
		
			
				|  |  | -= 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()
 | 
	
		
			
				|  |  | -----
 | 
	
		
			
				|  |  | -====
 |