mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-05-30 16:52:13 +00:00
Update ref doc for oauth2-client WebClient integration
Fixes gh-7404
This commit is contained in:
parent
38e87568a6
commit
52f0e5287b
@ -12,7 +12,7 @@ Below are the highlights of the release.
|
||||
** `authorization_code` grant support
|
||||
** `client_credentials` grant support
|
||||
* OAuth 2.0 Resource Server - support for {gh-samples-url}/boot/oauth2resourceserver[JWT-encoded bearer tokens]
|
||||
* Added OAuth2 <<servlet-webclient,WebClient>> integration
|
||||
* Added OAuth2 <<oauth2Client-webclient-servlet,WebClient>> integration
|
||||
* <<request-matching,HTTP Firewall>> protects against HTTP Verb Tampering and Cross-site Tracing
|
||||
* <<exception-translation-filter,ExceptionTranslationFilter>> support for selecting an `AccessDeniedHandler` by `RequestMatcher`
|
||||
* <<csrf,CSRF>> support for excluding certain requests
|
||||
|
@ -3,7 +3,7 @@
|
||||
[NOTE]
|
||||
====
|
||||
The following documentation is for use within Reactive environments.
|
||||
For Servlet environments, refer to <<servlet-webclient, WebClient for Servlet>> environments.
|
||||
For Servlet environments, refer to <<oauth2Client-webclient-servlet, WebClient for Servlet>> environments.
|
||||
====
|
||||
|
||||
|
||||
|
@ -1,102 +0,0 @@
|
||||
[[servlet-webclient]]
|
||||
== WebClient for Servlet Environments
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
The following documentation is for use within Servlet environments.
|
||||
For all other environments, refer to <<webclient, WebClient for Reactive>> environments.
|
||||
====
|
||||
|
||||
|
||||
Spring Framework has built in support for setting a Bearer token.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
webClient.get()
|
||||
.headers(h -> h.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.
|
||||
|
||||
[[servlet-webclient-setup]]
|
||||
=== 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:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@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();
|
||||
}
|
||||
----
|
||||
|
||||
[[servlet-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).
|
||||
|
||||
[source,java]
|
||||
----
|
||||
Mono<String> body = this.webClient
|
||||
.get()
|
||||
.uri(this.uri)
|
||||
.retrieve()
|
||||
.bodyToMono(String.class);
|
||||
----
|
||||
|
||||
[[servlet-webclient-explicit]]
|
||||
=== Explicit OAuth2AuthorizedClient
|
||||
|
||||
The `OAuth2AuthorizedClient` can be explicitly provided by setting it on the request 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.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@GetMapping("/explicit")
|
||||
Mono<String> explicit(@RegisteredOAuth2AuthorizedClient("client-id") OAuth2AuthorizedClient authorizedClient) {
|
||||
return this.webClient
|
||||
.get()
|
||||
.uri(this.uri)
|
||||
.attributes(oauth2AuthorizedClient(authorizedClient))
|
||||
.retrieve()
|
||||
.bodyToMono(String.class);
|
||||
}
|
||||
----
|
||||
|
||||
|
||||
[[servlet-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.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
Mono<String> body = this.webClient
|
||||
.get()
|
||||
.uri(this.uri)
|
||||
.attributes(clientRegistrationId("client-id"))
|
||||
.retrieve()
|
||||
.bodyToMono(String.class);
|
||||
----
|
@ -12,7 +12,7 @@ At a high-level, the core features available are:
|
||||
* https://tools.ietf.org/html/rfc6749#section-1.3.3[Resource Owner Password Credentials]
|
||||
|
||||
.HTTP Client support
|
||||
* <<servlet-webclient, `WebClient` integration for Servlet Environments>> (for requesting protected resources)
|
||||
* <<oauth2Client-webclient-servlet, `WebClient` integration for Servlet Environments>> (for requesting protected resources)
|
||||
|
||||
The `HttpSecurity.oauth2Client()` DSL provides a number of configuration options for customizing the core components used by OAuth 2.0 Client.
|
||||
In addition, `HttpSecurity.oauth2Client().authorizationCodeGrant()` enables the customization of the Authorization Code grant.
|
||||
@ -87,6 +87,7 @@ The following sections will go into more detail on the core components used by O
|
||||
** <<oauth2Client-password-grant, Resource Owner Password Credentials>>
|
||||
* <<oauth2Client-additional-features>>
|
||||
** <<oauth2Client-registered-authorized-client, Resolving an Authorized Client>>
|
||||
* <<oauth2Client-webclient-servlet>>
|
||||
|
||||
|
||||
[[oauth2Client-core-interface-class]]
|
||||
@ -1058,3 +1059,131 @@ The `@RegisteredOAuth2AuthorizedClient` annotation is handled by `OAuth2Authoriz
|
||||
** `client_credentials` - the access token is obtained directly from the Token Endpoint
|
||||
** `password` - the access token is obtained directly from the Token Endpoint
|
||||
* If the `OAuth2AccessToken` is expired, it will be renewed (or refreshed) if an `OAuth2AuthorizedClientProvider` is available to perform the authorization
|
||||
|
||||
|
||||
[[oauth2Client-webclient-servlet]]
|
||||
=== WebClient integration for Servlet Environments
|
||||
|
||||
The OAuth 2.0 Client support integrates with `WebClient` using an `ExchangeFilterFunction`.
|
||||
|
||||
The `ServletOAuth2AuthorizedClientExchangeFilterFunction` provides a simple mechanism for requesting protected resources by using an `OAuth2AuthorizedClient` and including the associated `OAuth2AccessToken` as a Bearer Token.
|
||||
It directly uses an <<oauth2Client-authorized-manager-provider, OAuth2AuthorizedClientManager>> and therefore inherits the following capabilities:
|
||||
|
||||
* An `OAuth2AccessToken` will be requested if the client has not yet been authorized.
|
||||
** `authorization_code` - triggers the Authorization Request redirect to initiate the flow
|
||||
** `client_credentials` - the access token is obtained directly from the Token Endpoint
|
||||
** `password` - the access token is obtained directly from the Token Endpoint
|
||||
* If the `OAuth2AccessToken` is expired, it will be refreshed (or renewed) if an `OAuth2AuthorizedClientProvider` is available to perform the authorization
|
||||
|
||||
The following code shows an example of how to configure `WebClient` with OAuth 2.0 Client support:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) {
|
||||
ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client =
|
||||
new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
|
||||
return WebClient.builder()
|
||||
.apply(oauth2Client.oauth2Configuration())
|
||||
.build();
|
||||
}
|
||||
----
|
||||
|
||||
[NOTE]
|
||||
Spring Boot 2.x auto-configuration registers an `OAuth2AuthorizedClientManager` `@Bean` in the `ApplicationContext`.
|
||||
|
||||
|
||||
==== Providing the Authorized Client
|
||||
|
||||
The `ServletOAuth2AuthorizedClientExchangeFilterFunction` determines the client to use (for a request) by resolving the `OAuth2AuthorizedClient` from the `ClientRequest.attributes()` (request attributes).
|
||||
|
||||
The following code shows how to set an `OAuth2AuthorizedClient` as a request attribute:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@GetMapping("/")
|
||||
public String index(@RegisteredOAuth2AuthorizedClient("okta") OAuth2AuthorizedClient authorizedClient) {
|
||||
String resourceUri = ...
|
||||
|
||||
String body = webClient
|
||||
.get()
|
||||
.uri(resourceUri)
|
||||
.attributes(oauth2AuthorizedClient(authorizedClient)) <1>
|
||||
.retrieve()
|
||||
.bodyToMono(String.class)
|
||||
.block();
|
||||
|
||||
...
|
||||
|
||||
return "index";
|
||||
}
|
||||
----
|
||||
<1> `oauth2AuthorizedClient()` is a `static` method in `ServletOAuth2AuthorizedClientExchangeFilterFunction`.
|
||||
|
||||
The following code shows how to set the `ClientRegistration.getRegistrationId()` as a request attribute:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@GetMapping("/")
|
||||
public String index() {
|
||||
String resourceUri = ...
|
||||
|
||||
String body = webClient
|
||||
.get()
|
||||
.uri(resourceUri)
|
||||
.attributes(clientRegistrationId("okta")) <1>
|
||||
.retrieve()
|
||||
.bodyToMono(String.class)
|
||||
.block();
|
||||
|
||||
...
|
||||
|
||||
return "index";
|
||||
}
|
||||
----
|
||||
<1> `clientRegistrationId()` is a `static` method in `ServletOAuth2AuthorizedClientExchangeFilterFunction`.
|
||||
|
||||
|
||||
==== Defaulting the Authorized Client
|
||||
|
||||
If neither `OAuth2AuthorizedClient` or `ClientRegistration.getRegistrationId()` is provided as a request attribute, the `ServletOAuth2AuthorizedClientExchangeFilterFunction` can determine the _default_ client to use depending on it's configuration.
|
||||
|
||||
If `setDefaultOAuth2AuthorizedClient(true)` is configured and the user has authenticated using `HttpSecurity.oauth2Login()`, the `OAuth2AccessToken` associated with the current `OAuth2AuthenticationToken` is used.
|
||||
|
||||
The following code shows the specific configuration:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) {
|
||||
ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client =
|
||||
new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
|
||||
oauth2Client.setDefaultOAuth2AuthorizedClient(true);
|
||||
return WebClient.builder()
|
||||
.apply(oauth2Client.oauth2Configuration())
|
||||
.build();
|
||||
}
|
||||
----
|
||||
|
||||
[WARNING]
|
||||
It is recommended to be cautious with this feature since all HTTP requests will receive the access token.
|
||||
|
||||
Alternatively, if `setDefaultClientRegistrationId("okta")` is configured with a valid `ClientRegistration`, the `OAuth2AccessToken` associated with the `OAuth2AuthorizedClient` is used.
|
||||
|
||||
The following code shows the specific configuration:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) {
|
||||
ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client =
|
||||
new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
|
||||
oauth2Client.setDefaultClientRegistrationId("okta");
|
||||
return WebClient.builder()
|
||||
.apply(oauth2Client.oauth2Configuration())
|
||||
.build();
|
||||
}
|
||||
----
|
||||
|
||||
[WARNING]
|
||||
It is recommended to be cautious with this feature since all HTTP requests will receive the access token.
|
||||
|
Loading…
x
Reference in New Issue
Block a user