From b77cb8d0cb38c311237b37ea631ea9b261836515 Mon Sep 17 00:00:00 2001 From: Joe Grandja Date: Thu, 28 Oct 2021 09:17:13 -0400 Subject: [PATCH] Remove redundant docs for Reactive OAuth2 Client Issue gh-10373 --- docs/modules/ROOT/nav.adoc | 2 - .../reactive/integrations/webclient.adoc | 175 ------------------ .../registered-oauth2-authorized-client.adoc | 63 ------- 3 files changed, 240 deletions(-) delete mode 100644 docs/modules/ROOT/pages/reactive/integrations/webclient.adoc delete mode 100644 docs/modules/ROOT/pages/reactive/registered-oauth2-authorized-client.adoc diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc index 529a2fcb78..7b7c724527 100644 --- a/docs/modules/ROOT/nav.adoc +++ b/docs/modules/ROOT/nav.adoc @@ -96,7 +96,6 @@ *** xref:reactive/oauth2/login.adoc[OAuth2 Log In] *** xref:reactive/oauth2/oauth2-client.adoc[OAuth2 Client] *** xref:reactive/oauth2/resource-server.adoc[OAuth2 Resource Server] -*** xref:reactive/registered-oauth2-authorized-client.adoc[@RegisteredOAuth2AuthorizedClient] ** xref:reactive/exploits/index.adoc[Protection Against Exploits] *** xref:reactive/exploits/csrf.adoc[CSRF] *** xref:reactive/exploits/headers.adoc[Headers] @@ -104,6 +103,5 @@ ** Integrations *** xref:reactive/integrations/cors.adoc[CORS] *** xref:reactive/integrations/rsocket.adoc[RSocket] -*** xref:reactive/integrations/webclient.adoc[WebClient] ** xref:reactive/test.adoc[Testing] ** xref:reactive/configuration/webflux.adoc[WebFlux Security] diff --git a/docs/modules/ROOT/pages/reactive/integrations/webclient.adoc b/docs/modules/ROOT/pages/reactive/integrations/webclient.adoc deleted file mode 100644 index 270420a4fa..0000000000 --- a/docs/modules/ROOT/pages/reactive/integrations/webclient.adoc +++ /dev/null @@ -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 body = this.webClient - .get() - .uri(this.uri) - .retrieve() - .bodyToMono(String.class); ----- - -.Kotlin -[source,kotlin,role="secondary"] ----- -val body: Mono = 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 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 { - 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 body = this.webClient - .get() - .uri(this.uri) - .attributes(clientRegistrationId("client-id")) - .retrieve() - .bodyToMono(String.class); ----- - -.Kotlin -[source,kotlin,role="secondary"] ----- -val body: Mono = this.webClient - .get() - .uri(uri) - .attributes(clientRegistrationId("client-id")) - .retrieve() - .bodyToMono() ----- -==== diff --git a/docs/modules/ROOT/pages/reactive/registered-oauth2-authorized-client.adoc b/docs/modules/ROOT/pages/reactive/registered-oauth2-authorized-client.adoc deleted file mode 100644 index 1374267de0..0000000000 --- a/docs/modules/ROOT/pages/reactive/registered-oauth2-authorized-client.adoc +++ /dev/null @@ -1,63 +0,0 @@ -[[webflux-roac]] -= @RegisteredOAuth2AuthorizedClient - -Spring Security allows resolving an access token using `@RegisteredOAuth2AuthorizedClient`. - -[NOTE] -==== -A working example can be found in {gh-samples-url}/reactive/webflux/java/oauth2/webclient[*OAuth 2.0 WebClient WebFlux sample*]. -==== - -After configuring Spring Security for xref:reactive/oauth2/login.adoc#webflux-oauth2-login[OAuth2 Login] or as an xref:reactive/oauth2/oauth2-client.adoc#webflux-oauth2-client[OAuth2 Client], an `OAuth2AuthorizedClient` can be resolved using the following: - -==== -.Java -[source,java,role="primary"] ----- -@GetMapping("/explicit") -Mono explicit(@RegisteredOAuth2AuthorizedClient("client-id") OAuth2AuthorizedClient authorizedClient) { - // ... -} ----- - -.Kotlin -[source,kotlin,role="secondary"] ----- -@GetMapping("/explicit") -fun explicit(@RegisteredOAuth2AuthorizedClient("client-id") authorizedClient: OAuth2AuthorizedClient?): Mono { - // ... -} ----- -==== - -This integrates into Spring Security to provide the following features: - -* 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 - -If the user authenticated using `oauth2Login()`, then the `client-id` is optional. -For example, the following would work: - -==== -.Java -[source,java,role="primary"] ----- -@GetMapping("/implicit") -Mono implicit(@RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authorizedClient) { - // ... -} ----- - -.Kotlin -[source,kotlin,role="secondary"] ----- -@GetMapping("/implicit") -fun implicit(@RegisteredOAuth2AuthorizedClient authorizedClient: OAuth2AuthorizedClient?): Mono { - // ... -} ----- -==== - -This is convenient if the user always authenticates with OAuth2 Login and an access token from the same authorization server is needed.