|
@@ -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()
|
|
|
-----
|
|
|
-====
|