Document RestClient-based implementations

Closes gh-15938
This commit is contained in:
Steve Riesenberg 2024-10-17 10:50:59 -05:00
parent d0fc4fe4dc
commit 8982851355
No known key found for this signature in database
GPG Key ID: 3D0169B18AB8F0A9
5 changed files with 573 additions and 357 deletions

View File

@ -1,16 +1,18 @@
[[oauth2Client-auth-grant-support]]
= Authorization Grant Support
[[oauth2-client-authorization-grants]]
= [[oauth2Client-auth-grant-support]]Authorization Grant Support
:spring-security-reference-base-url: https://docs.spring.io/spring-security/reference
This section describes Spring Security's support for authorization grants.
[[oauth2Client-auth-code-grant]]
== Authorization Code
[[oauth2-client-authorization-code]]
== [[oauth2Client-auth-code-grant]]Authorization Code
[NOTE]
====
See the OAuth 2.0 Authorization Framework for further details on the https://tools.ietf.org/html/rfc6749#section-1.3.1[Authorization Code] grant.
====
[[oauth2-client-authorization-code-authorization]]
=== Obtaining Authorization
[NOTE]
@ -18,8 +20,7 @@ See the OAuth 2.0 Authorization Framework for further details on the https://too
See the https://tools.ietf.org/html/rfc6749#section-4.1.1[Authorization Request/Response] protocol flow for the Authorization Code grant.
====
[[oauth2-client-authorization-code-authorization-request]]
=== Initiating the Authorization Request
The `OAuth2AuthorizationRequestRedirectFilter` uses an `OAuth2AuthorizationRequestResolver` to resolve an `OAuth2AuthorizationRequest` and initiate the Authorization Code grant flow by redirecting the end-user's user-agent to the Authorization Server's Authorization Endpoint.
@ -70,7 +71,7 @@ spring:
client-authentication-method: none
authorization-grant-type: authorization_code
redirect-uri: "{baseUrl}/authorized/okta"
...
# ...
----
Public Clients are supported by using https://tools.ietf.org/html/rfc7636[Proof Key for Code Exchange] (PKCE).
@ -82,8 +83,8 @@ If the client is running in an untrusted environment (such as a native applicati
[TIP]
If the OAuth 2.0 Provider supports PKCE for https://tools.ietf.org/html/rfc6749#section-2.1[Confidential Clients], you may (optionally) configure it using `DefaultOAuth2AuthorizationRequestResolver.setAuthorizationRequestCustomizer(OAuth2AuthorizationRequestCustomizers.withPkce())`.
[[oauth2Client-auth-code-redirect-uri]]
The `DefaultOAuth2AuthorizationRequestResolver` also supports `URI` template variables for the `redirect-uri` by using `UriComponentsBuilder`.
[[oauth2-client-authorization-code-redirect-uri]]
[[oauth2Client-auth-code-redirect-uri]]The `DefaultOAuth2AuthorizationRequestResolver` also supports `URI` template variables for the `redirect-uri` by using `UriComponentsBuilder`.
The following configuration uses all the supported `URI` template variables:
@ -95,9 +96,9 @@ spring:
client:
registration:
okta:
...
# ...
redirect-uri: "{baseScheme}://{baseHost}{basePort}{basePath}/authorized/{registrationId}"
...
# ...
----
[NOTE]
@ -108,6 +109,7 @@ spring:
Configuring the `redirect-uri` with `URI` template variables is especially useful when the OAuth 2.0 Client is running behind a xref:features/exploits/http.adoc#http-proxy-server[Proxy Server].
Doing so ensures that the `X-Forwarded-*` headers are used when expanding the `redirect-uri`.
[[oauth2-client-authorization-code-authorization-request-resolver]]
=== Customizing the Authorization Request
One of the primary use cases an `OAuth2AuthorizationRequestResolver` can realize is the ability to customize the Authorization Request with additional parameters above the standard parameters defined in the OAuth 2.0 Authorization Framework.
@ -197,7 +199,7 @@ class SecurityConfig {
}
private fun authorizationRequestResolver(
clientRegistrationRepository: ClientRegistrationRepository?): OAuth2AuthorizationRequestResolver? {
clientRegistrationRepository: ClientRegistrationRepository?): OAuth2AuthorizationRequestResolver {
val authorizationRequestResolver = DefaultOAuth2AuthorizationRequestResolver(
clientRegistrationRepository, "/oauth2/authorization")
authorizationRequestResolver.setAuthorizationRequestCustomizer(
@ -269,7 +271,7 @@ private fun authorizationRequestCustomizer(): Consumer<OAuth2AuthorizationReques
----
======
[[oauth2-client-authorization-code-authorization-request-repository]]
=== Storing the Authorization Request
The `AuthorizationRequestRepository` is responsible for the persistence of the `OAuth2AuthorizationRequest` from the time the Authorization Request is initiated to the time the Authorization Response is received (the callback).
@ -300,14 +302,16 @@ public class OAuth2ClientSecurityConfig {
.oauth2Client(oauth2 -> oauth2
.authorizationCodeGrant(codeGrant -> codeGrant
.authorizationRequestRepository(this.authorizationRequestRepository())
...
// ...
)
)
.oauth2Login(oauth2 -> oauth2
.authorizationEndpoint(endpoint -> endpoint
.authorizationRequestRepository(this.authorizationRequestRepository())
...
// ...
)
).build();
);
return http.build();
}
@Bean
@ -351,6 +355,7 @@ Xml::
----
======
[[oauth2-client-authorization-code-access-token]]
=== Requesting an Access Token
[NOTE]
@ -358,73 +363,35 @@ Xml::
See the https://tools.ietf.org/html/rfc6749#section-4.1.3[Access Token Request/Response] protocol flow for the Authorization Code grant.
====
The default implementation of `OAuth2AccessTokenResponseClient` for the Authorization Code grant is `DefaultAuthorizationCodeTokenResponseClient`, which uses a `RestOperations` instance to exchange an authorization code for an access token at the Authorization Servers Token Endpoint.
There are two implementations of `OAuth2AccessTokenResponseClient` that can be used to make HTTP requests to the Token Endpoint in order to obtain an access token for the Authorization Code grant:
The `DefaultAuthorizationCodeTokenResponseClient` is flexible, as it lets you customize the pre-processing of the Token Request and/or post-handling of the Token Response.
* `DefaultAuthorizationCodeTokenResponseClient` (_default_)
* `RestClientAuthorizationCodeTokenResponseClient`
The default implementation uses a `RestOperations` instance to exchange an authorization code for an access token at the Authorization Servers Token Endpoint.
Spring Security 6.4 introduces a new implementation based on `RestClient`, which provides similar functionality but is better aligned with the Reactive version of the component (based on `WebClient`) in order to provide consistent configuration for applications on either stack.
=== Customizing the Access Token Request
If you need to customize the pre-processing of the Token Request, you can provide `DefaultAuthorizationCodeTokenResponseClient.setRequestEntityConverter()` with a custom `Converter<OAuth2AuthorizationCodeGrantRequest, RequestEntity<?>>`.
The default implementation (`OAuth2AuthorizationCodeGrantRequestEntityConverter`) builds a `RequestEntity` representation of a standard https://tools.ietf.org/html/rfc6749#section-4.1.3[OAuth 2.0 Access Token Request].
However, providing a custom `Converter` would let you extend the standard Token Request and add custom parameter(s).
To customize only the parameters of the request, you can provide `OAuth2AuthorizationCodeGrantRequestEntityConverter.setParametersConverter()` with a custom `Converter<OAuth2AuthorizationCodeGrantRequest, MultiValueMap<String, String>>` to completely override the parameters sent with the request. This is often simpler than constructing a `RequestEntity` directly.
[TIP]
[NOTE]
====
If you prefer to only add additional parameters, you can provide `OAuth2AuthorizationCodeGrantRequestEntityConverter.addParametersConverter()` with a custom `Converter<OAuth2AuthorizationCodeGrantRequest, MultiValueMap<String, String>>` which constructs an aggregate `Converter`.
This section focuses on `RestClientAuthorizationCodeTokenResponseClient`.
You can read about {spring-security-reference-base-url}/6.3/servlet/oauth2/client/authorization-grants.html#_requesting_an_access_token[`DefaultAuthorizationCodeTokenResponseClient`] in the Spring Security 6.3 documentation.
====
[IMPORTANT]
====
The custom `Converter` must return a valid `RequestEntity` representation of an OAuth 2.0 Access Token Request that is understood by the intended OAuth 2.0 Provider.
====
:section-id: authorization-code
:grant-type: Authorization Code
:class-name: RestClientAuthorizationCodeTokenResponseClient
:grant-request: OAuth2AuthorizationCodeGrantRequest
:leveloffset: +1
include::partial$servlet/oauth2/client/rest-client-access-token-response-client.adoc[]
=== Customizing the Access Token Response
:leveloffset: -1
On the other end, if you need to customize the post-handling of the Token Response, you need to provide `DefaultAuthorizationCodeTokenResponseClient.setRestOperations()` with a custom configured `RestOperations`.
The default `RestOperations` is configured as follows:
[[oauth2-client-authorization-code-access-token-response-client-dsl]]
=== Customize using the DSL
[tabs]
======
Java::
+
[source,java,role="primary"]
----
RestTemplate restTemplate = new RestTemplate(Arrays.asList(
new FormHttpMessageConverter(),
new OAuth2AccessTokenResponseHttpMessageConverter()));
Whether you customize `{class-name}` or provide your own implementation of `OAuth2AccessTokenResponseClient`, you can configure it using the DSL (as an alternative to <<oauth2-client-authorization-code-access-token-response-client-bean,publishing a bean>>) as follows:
restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
----
Kotlin::
+
[source,kotlin,role="secondary"]
----
val restTemplate = RestTemplate(listOf(
FormHttpMessageConverter(),
OAuth2AccessTokenResponseHttpMessageConverter()))
restTemplate.errorHandler = OAuth2ErrorResponseErrorHandler()
----
======
[TIP]
====
Spring MVC `FormHttpMessageConverter` is required, as it is used when sending the OAuth 2.0 Access Token Request.
====
`OAuth2AccessTokenResponseHttpMessageConverter` is an `HttpMessageConverter` for an OAuth 2.0 Access Token Response.
You can provide `OAuth2AccessTokenResponseHttpMessageConverter.setAccessTokenResponseConverter()` with a custom `Converter<Map<String, Object>, OAuth2AccessTokenResponse>` that is used for converting the OAuth 2.0 Access Token Response parameters to an `OAuth2AccessTokenResponse`.
`OAuth2ErrorResponseErrorHandler` is a `ResponseErrorHandler` that can handle an OAuth 2.0 Error, such as `400 Bad Request`.
It uses an `OAuth2ErrorHttpMessageConverter` for converting the OAuth 2.0 Error parameters to an `OAuth2Error`.
Whether you customize `DefaultAuthorizationCodeTokenResponseClient` or provide your own implementation of `OAuth2AccessTokenResponseClient`, you need to configure it as follows:
.Access Token Response Configuration
.Access Token Response Configuration via DSL
[tabs]
======
Java::
@ -441,7 +408,7 @@ public class OAuth2ClientSecurityConfig {
.oauth2Client(oauth2 -> oauth2
.authorizationCodeGrant(codeGrant -> codeGrant
.accessTokenResponseClient(this.accessTokenResponseClient())
...
// ...
)
);
return http.build();
@ -483,16 +450,15 @@ Xml::
----
======
[[oauth2Client-refresh-token-grant]]
== Refresh Token
[[oauth2-client-refresh-token]]
== [[oauth2Client-refresh-token-grant]]Refresh Token
[NOTE]
====
See the OAuth 2.0 Authorization Framework for further details on the https://tools.ietf.org/html/rfc6749#section-1.5[Refresh Token].
====
[[oauth2-client-refresh-token-access-token]]
=== Refreshing an Access Token
[NOTE]
@ -500,72 +466,33 @@ See the OAuth 2.0 Authorization Framework for further details on the https://too
See the https://tools.ietf.org/html/rfc6749#section-6[Access Token Request/Response] protocol flow for the Refresh Token grant.
====
The default implementation of `OAuth2AccessTokenResponseClient` for the Refresh Token grant is `DefaultRefreshTokenTokenResponseClient`, which uses a `RestOperations` when refreshing an access token at the Authorization Servers Token Endpoint.
There are two implementations of `OAuth2AccessTokenResponseClient` that can be used to make HTTP requests to the Token Endpoint in order to obtain an access token for the Refresh Token grant:
The `DefaultRefreshTokenTokenResponseClient` is flexible, as it lets you customize the pre-processing of the Token Request or post-handling of the Token Response.
* `DefaultRefreshTokenTokenResponseClient` (_default_)
* `RestClientRefreshTokenTokenResponseClient`
The default implementation uses a `RestOperations` instance to exchange an authorization code for an access token at the Authorization Servers Token Endpoint.
Spring Security 6.4 introduces a new implementation based on `RestClient`, which provides similar functionality but is better aligned with the Reactive version of the component (based on `WebClient`) in order to provide consistent configuration for applications on either stack.
=== Customizing the Access Token Request
If you need to customize the pre-processing of the Token Request, you can provide `DefaultRefreshTokenTokenResponseClient.setRequestEntityConverter()` with a custom `Converter<OAuth2RefreshTokenGrantRequest, RequestEntity<?>>`.
The default implementation (`OAuth2RefreshTokenGrantRequestEntityConverter`) builds a `RequestEntity` representation of a standard https://tools.ietf.org/html/rfc6749#section-6[OAuth 2.0 Access Token Request].
However, providing a custom `Converter` would let you extend the standard Token Request and add custom parameter(s).
To customize only the parameters of the request, you can provide `OAuth2RefreshTokenGrantRequestEntityConverter.setParametersConverter()` with a custom `Converter<OAuth2RefreshTokenGrantRequest, MultiValueMap<String, String>>` to completely override the parameters sent with the request. This is often simpler than constructing a `RequestEntity` directly.
[TIP]
[NOTE]
====
If you prefer to only add additional parameters, you can provide `OAuth2RefreshTokenGrantRequestEntityConverter.addParametersConverter()` with a custom `Converter<OAuth2RefreshTokenGrantRequest, MultiValueMap<String, String>>` which constructs an aggregate `Converter`.
This section focuses on `RestClientRefreshTokenTokenResponseClient`.
You can read about {spring-security-reference-base-url}/6.3/servlet/oauth2/client/authorization-grants.html#_refreshing_an_access_token[`DefaultRefreshTokenTokenResponseClient`] in the Spring Security 6.3 documentation.
====
[IMPORTANT]
====
The custom `Converter` must return a valid `RequestEntity` representation of an OAuth 2.0 Access Token Request that is understood by the intended OAuth 2.0 Provider.
====
:section-id: refresh-token
:grant-type: Refresh Token
:class-name: RestClientRefreshTokenTokenResponseClient
:grant-request: OAuth2RefreshTokenGrantRequest
:leveloffset: +1
include::partial$servlet/oauth2/client/rest-client-access-token-response-client.adoc[]
:leveloffset: -1
=== Customizing the Access Token Response
[[oauth2-client-refresh-token-authorized-client-provider-builder]]
=== Customize using the Builder
On the other end, if you need to customize the post-handling of the Token Response, you need to provide `DefaultRefreshTokenTokenResponseClient.setRestOperations()` with a custom configured `RestOperations`.
The default `RestOperations` is configured as follows:
[tabs]
======
Java::
+
[source,java,role="primary"]
----
RestTemplate restTemplate = new RestTemplate(Arrays.asList(
new FormHttpMessageConverter(),
new OAuth2AccessTokenResponseHttpMessageConverter()));
restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
----
Kotlin::
+
[source,kotlin,role="secondary"]
----
val restTemplate = RestTemplate(listOf(
FormHttpMessageConverter(),
OAuth2AccessTokenResponseHttpMessageConverter()))
restTemplate.errorHandler = OAuth2ErrorResponseErrorHandler()
----
======
[TIP]
====
Spring MVC `FormHttpMessageConverter` is required, as it is used when sending the OAuth 2.0 Access Token Request.
====
`OAuth2AccessTokenResponseHttpMessageConverter` is a `HttpMessageConverter` for an OAuth 2.0 Access Token Response.
You can provide `OAuth2AccessTokenResponseHttpMessageConverter.setAccessTokenResponseConverter()` with a custom `Converter<Map<String, Object>, OAuth2AccessTokenResponse>` that is used for converting the OAuth 2.0 Access Token Response parameters to an `OAuth2AccessTokenResponse`.
`OAuth2ErrorResponseErrorHandler` is a `ResponseErrorHandler` that can handle an OAuth 2.0 Error, such as `400 Bad Request`.
It uses an `OAuth2ErrorHttpMessageConverter` for converting the OAuth 2.0 Error parameters to an `OAuth2Error`.
Whether you customize `DefaultRefreshTokenTokenResponseClient` or provide your own implementation of `OAuth2AccessTokenResponseClient`, you need to configure it as follows:
Whether you customize `RestClientRefreshTokenTokenResponseClient` or provide your own implementation of `OAuth2AccessTokenResponseClient`, you can configure it using the `OAuth2AuthorizedClientProviderBuilder` (as an alternative to <<oauth2-client-refresh-token-access-token-response-client-bean,publishing a bean>>) as follows:
[tabs]
======
@ -582,7 +509,7 @@ OAuth2AuthorizedClientProvider authorizedClientProvider =
.refreshToken(configurer -> configurer.accessTokenResponseClient(refreshTokenTokenResponseClient))
.build();
...
// ...
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
----
@ -599,7 +526,7 @@ val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.refreshToken { it.accessTokenResponseClient(refreshTokenTokenResponseClient) }
.build()
...
// ...
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
----
@ -614,14 +541,15 @@ which is an implementation of an `OAuth2AuthorizedClientProvider` for the Refres
The `OAuth2RefreshToken` can optionally be returned in the Access Token Response for the `authorization_code` and `password` grant types.
If the `OAuth2AuthorizedClient.getRefreshToken()` is available and the `OAuth2AuthorizedClient.getAccessToken()` is expired, it is automatically refreshed by the `RefreshTokenOAuth2AuthorizedClientProvider`.
[[oauth2Client-client-creds-grant]]
== Client Credentials
[[oauth2-client-client-credentials]]
== [[oauth2Client-client-creds-grant]]Client Credentials
[NOTE]
====
Please refer to the OAuth 2.0 Authorization Framework for further details on the https://tools.ietf.org/html/rfc6749#section-1.3.4[Client Credentials] grant.
====
[[oauth2-client-client-credentials-access-token]]
=== Requesting an Access Token
[NOTE]
@ -629,72 +557,33 @@ Please refer to the OAuth 2.0 Authorization Framework for further details on the
See the OAuth 2.0 Authorization Framework for further details on the https://tools.ietf.org/html/rfc6749#section-1.3.4[Client Credentials] grant.
====
The default implementation of `OAuth2AccessTokenResponseClient` for the Client Credentials grant is `DefaultClientCredentialsTokenResponseClient`, which uses a `RestOperations` when requesting an access token at the Authorization Servers Token Endpoint.
There are two implementations of `OAuth2AccessTokenResponseClient` that can be used to make HTTP requests to the Token Endpoint in order to obtain an access token for the Client Credentials grant:
The `DefaultClientCredentialsTokenResponseClient` is flexible, as it lets you customize the pre-processing of the Token Request or post-handling of the Token Response.
* `DefaultClientCredentialsTokenResponseClient` (_default_)
* `RestClientClientCredentialsTokenResponseClient`
The default implementation uses a `RestOperations` instance to exchange an authorization code for an access token at the Authorization Servers Token Endpoint.
Spring Security 6.4 introduces a new implementation based on `RestClient`, which provides similar functionality but is better aligned with the Reactive version of the component (based on `WebClient`) in order to provide consistent configuration for applications on either stack.
=== Customizing the Access Token Request
If you need to customize the pre-processing of the Token Request, you can provide `DefaultClientCredentialsTokenResponseClient.setRequestEntityConverter()` with a custom `Converter<OAuth2ClientCredentialsGrantRequest, RequestEntity<?>>`.
The default implementation (`OAuth2ClientCredentialsGrantRequestEntityConverter`) builds a `RequestEntity` representation of a standard https://tools.ietf.org/html/rfc6749#section-4.4.2[OAuth 2.0 Access Token Request].
However, providing a custom `Converter` would let you extend the standard Token Request and add custom parameter(s).
To customize only the parameters of the request, you can provide `OAuth2ClientCredentialsGrantRequestEntityConverter.setParametersConverter()` with a custom `Converter<OAuth2ClientCredentialsGrantRequest, MultiValueMap<String, String>>` to completely override the parameters sent with the request. This is often simpler than constructing a `RequestEntity` directly.
[TIP]
[NOTE]
====
If you prefer to only add additional parameters, you can provide `OAuth2ClientCredentialsGrantRequestEntityConverter.addParametersConverter()` with a custom `Converter<OAuth2ClientCredentialsGrantRequest, MultiValueMap<String, String>>` which constructs an aggregate `Converter`.
This section focuses on `RestClientClientCredentialsTokenResponseClient`.
You can read about {spring-security-reference-base-url}/6.3/servlet/oauth2/client/authorization-grants.html#_requesting_an_access_token_2[`DefaultClientCredentialsTokenResponseClient`] in the Spring Security 6.3 documentation.
====
[IMPORTANT]
====
The custom `Converter` must return a valid `RequestEntity` representation of an OAuth 2.0 Access Token Request that is understood by the intended OAuth 2.0 Provider.
====
:section-id: client-credentials
:grant-type: Client Credentials
:class-name: RestClientClientCredentialsTokenResponseClient
:grant-request: OAuth2ClientCredentialsGrantRequest
:leveloffset: +1
include::partial$servlet/oauth2/client/rest-client-access-token-response-client.adoc[]
:leveloffset: -1
=== Customizing the Access Token Response
[[oauth2-client-client-credentials-authorized-client-provider-builder]]
=== Customize using the Builder
On the other end, if you need to customize the post-handling of the Token Response, you need to provide `DefaultClientCredentialsTokenResponseClient.setRestOperations()` with a custom configured `RestOperations`.
The default `RestOperations` is configured as follows:
[tabs]
======
Java::
+
[source,java,role="primary"]
----
RestTemplate restTemplate = new RestTemplate(Arrays.asList(
new FormHttpMessageConverter(),
new OAuth2AccessTokenResponseHttpMessageConverter()));
restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
----
Kotlin::
+
[source,kotlin,role="secondary"]
----
val restTemplate = RestTemplate(listOf(
FormHttpMessageConverter(),
OAuth2AccessTokenResponseHttpMessageConverter()))
restTemplate.errorHandler = OAuth2ErrorResponseErrorHandler()
----
======
[TIP]
====
Spring MVC `FormHttpMessageConverter` is required, as it is used when sending the OAuth 2.0 Access Token Request.
====
`OAuth2AccessTokenResponseHttpMessageConverter` is a `HttpMessageConverter` for an OAuth 2.0 Access Token Response.
You can provide `OAuth2AccessTokenResponseHttpMessageConverter.setAccessTokenResponseConverter()` with a custom `Converter<Map<String, Object>, OAuth2AccessTokenResponse>` that is used for converting the OAuth 2.0 Access Token Response parameters to an `OAuth2AccessTokenResponse`.
`OAuth2ErrorResponseErrorHandler` is a `ResponseErrorHandler` that can handle an OAuth 2.0 Error, such as `400 Bad Request`.
It uses an `OAuth2ErrorHttpMessageConverter` to convert the OAuth 2.0 Error parameters to an `OAuth2Error`.
Whether you customize `DefaultClientCredentialsTokenResponseClient` or provide your own implementation of `OAuth2AccessTokenResponseClient`, you need to configure it as follows:
Whether you customize `RestClientClientCredentialsTokenResponseClient` or provide your own implementation of `OAuth2AccessTokenResponseClient`, you can configure it using the `OAuth2AuthorizedClientProviderBuilder` (as an alternative to <<oauth2-client-client-credentials-access-token-response-client-bean,publishing a bean>>) as follows:
[tabs]
======
@ -710,7 +599,7 @@ OAuth2AuthorizedClientProvider authorizedClientProvider =
.clientCredentials(configurer -> configurer.accessTokenResponseClient(clientCredentialsTokenResponseClient))
.build();
...
// ...
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
----
@ -726,7 +615,7 @@ val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials { it.accessTokenResponseClient(clientCredentialsTokenResponseClient) }
.build()
...
// ...
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
----
@ -738,6 +627,7 @@ authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
which is an implementation of an `OAuth2AuthorizedClientProvider` for the Client Credentials grant.
====
[[oauth2-client-client-credentials-authorized-client-manager]]
=== Using the Access Token
Consider the following Spring Boot properties for an OAuth 2.0 Client registration:
@ -835,7 +725,7 @@ public class OAuth2ClientController {
OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
...
// ...
return "index";
}
@ -865,7 +755,7 @@ class OAuth2ClientController {
val authorizedClient = authorizedClientManager.authorize(authorizeRequest)
val accessToken: OAuth2AccessToken = authorizedClient.accessToken
...
// ...
return "index"
}
@ -879,14 +769,15 @@ class OAuth2ClientController {
If not provided, they default to `ServletRequestAttributes` by using `RequestContextHolder.getRequestAttributes()`.
====
[[oauth2Client-password-grant]]
== Resource Owner Password Credentials
[[oauth2-client-password]]
== [[oauth2Client-password-grant]]Resource Owner Password Credentials
[NOTE]
====
See the OAuth 2.0 Authorization Framework for further details on the https://tools.ietf.org/html/rfc6749#section-1.3.3[Resource Owner Password Credentials] grant.
====
[[oauth2-client-password-access-token]]
=== Requesting an Access Token
[NOTE]
@ -896,8 +787,15 @@ See the https://tools.ietf.org/html/rfc6749#section-4.3.2[Access Token Request/R
The default implementation of `OAuth2AccessTokenResponseClient` for the Resource Owner Password Credentials grant is `DefaultPasswordTokenResponseClient`, which uses a `RestOperations` when requesting an access token at the Authorization Servers Token Endpoint.
[CAUTION]
====
The `DefaultPasswordTokenResponseClient` class and support for the Resource Owner Password Credentials grant are deprecated.
This section will be removed in Spring Security 7.
====
The `DefaultPasswordTokenResponseClient` is flexible, as it lets you customize the pre-processing of the Token Request or post-handling of the Token Response.
[[oauth2-client-password-access-token-request]]
=== Customizing the Access Token Request
If you need to customize the pre-processing of the Token Request, you can provide `DefaultPasswordTokenResponseClient.setRequestEntityConverter()` with a custom `Converter<OAuth2PasswordGrantRequest, RequestEntity<?>>`.
@ -916,7 +814,7 @@ If you prefer to only add additional parameters, you can provide `OAuth2Password
The custom `Converter` must return a valid `RequestEntity` representation of an OAuth 2.0 Access Token Request that is understood by the intended OAuth 2.0 Provider.
====
[[oauth2-client-password-access-token-response]]
=== Customizing the Access Token Response
On the other end, if you need to customize the post-handling of the Token Response, you need to provide `DefaultPasswordTokenResponseClient.setRestOperations()` with a custom configured `RestOperations`.
@ -958,6 +856,9 @@ You can provide `OAuth2AccessTokenResponseHttpMessageConverter.setTokenResponseC
`OAuth2ErrorResponseErrorHandler` is a `ResponseErrorHandler` that can handle an OAuth 2.0 Error, such as `400 Bad Request`.
It uses an `OAuth2ErrorHttpMessageConverter` to convert the OAuth 2.0 Error parameters to an `OAuth2Error`.
[[oauth2-client-password-authorized-client-provider-builder]]
=== Customize using the Builder
Whether you customize `DefaultPasswordTokenResponseClient` or provide your own implementation of `OAuth2AccessTokenResponseClient`, you need to configure it as follows:
[tabs]
@ -975,7 +876,7 @@ OAuth2AuthorizedClientProvider authorizedClientProvider =
.refreshToken()
.build();
...
// ...
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
----
@ -991,7 +892,7 @@ val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.refreshToken()
.build()
...
// ...
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
----
@ -1003,6 +904,7 @@ authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
which is an implementation of an `OAuth2AuthorizedClientProvider` for the Resource Owner Password Credentials grant.
====
[[oauth2-client-password-authorized-client-manager]]
=== Using the Access Token
Consider the following Spring Boot properties for an OAuth 2.0 Client registration:
@ -1144,7 +1046,7 @@ public class OAuth2ClientController {
OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
...
// ...
return "index";
}
@ -1174,7 +1076,7 @@ class OAuth2ClientController {
val authorizedClient = authorizedClientManager.authorize(authorizeRequest)
val accessToken: OAuth2AccessToken = authorizedClient.accessToken
...
// ...
return "index"
}
@ -1188,16 +1090,15 @@ class OAuth2ClientController {
If not provided, they default to `ServletRequestAttributes` using `RequestContextHolder.getRequestAttributes()`.
====
[[oauth2Client-jwt-bearer-grant]]
== JWT Bearer
[[oauth2-client-jwt-bearer]]
== [[oauth2Client-jwt-bearer-grant]]JWT Bearer
[NOTE]
====
Please refer to JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants for further details on the https://datatracker.ietf.org/doc/html/rfc7523[JWT Bearer] grant.
====
[[oauth2-client-jwt-bearer-access-token]]
=== Requesting an Access Token
[NOTE]
@ -1205,65 +1106,33 @@ Please refer to JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication
Please refer to the https://datatracker.ietf.org/doc/html/rfc7523#section-2.1[Access Token Request/Response] protocol flow for the JWT Bearer grant.
====
The default implementation of `OAuth2AccessTokenResponseClient` for the JWT Bearer grant is `DefaultJwtBearerTokenResponseClient`, which uses a `RestOperations` when requesting an access token at the Authorization Servers Token Endpoint.
There are two implementations of `OAuth2AccessTokenResponseClient` that can be used to make HTTP requests to the Token Endpoint in order to obtain an access token for the JWT Bearer grant:
The `DefaultJwtBearerTokenResponseClient` is quite flexible as it allows you to customize the pre-processing of the Token Request and/or post-handling of the Token Response.
* `DefaultJwtBearerTokenResponseClient` (_default_)
* `RestClientJwtBearerTokenResponseClient`
The default implementation uses a `RestOperations` instance to exchange an authorization code for an access token at the Authorization Servers Token Endpoint.
Spring Security 6.4 introduces a new implementation based on `RestClient`, which provides similar functionality but is better aligned with the Reactive version of the component (based on `WebClient`) in order to provide consistent configuration for applications on either stack.
=== Customizing the Access Token Request
If you need to customize the pre-processing of the Token Request, you can provide `DefaultJwtBearerTokenResponseClient.setRequestEntityConverter()` with a custom `Converter<JwtBearerGrantRequest, RequestEntity<?>>`.
The default implementation `JwtBearerGrantRequestEntityConverter` builds a `RequestEntity` representation of a https://datatracker.ietf.org/doc/html/rfc7523#section-2.1[OAuth 2.0 Access Token Request].
However, providing a custom `Converter`, would allow you to extend the Token Request and add custom parameter(s).
To customize only the parameters of the request, you can provide `JwtBearerGrantRequestEntityConverter.setParametersConverter()` with a custom `Converter<JwtBearerGrantRequest, MultiValueMap<String, String>>` to completely override the parameters sent with the request. This is often simpler than constructing a `RequestEntity` directly.
[TIP]
If you prefer to only add additional parameters, you can provide `JwtBearerGrantRequestEntityConverter.addParametersConverter()` with a custom `Converter<JwtBearerGrantRequest, MultiValueMap<String, String>>` which constructs an aggregate `Converter`.
=== Customizing the Access Token Response
On the other end, if you need to customize the post-handling of the Token Response, you will need to provide `DefaultJwtBearerTokenResponseClient.setRestOperations()` with a custom configured `RestOperations`.
The default `RestOperations` is configured as follows:
[tabs]
======
Java::
+
[source,java,role="primary"]
----
RestTemplate restTemplate = new RestTemplate(Arrays.asList(
new FormHttpMessageConverter(),
new OAuth2AccessTokenResponseHttpMessageConverter()));
restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
----
Kotlin::
+
[source,kotlin,role="secondary"]
----
val restTemplate = RestTemplate(listOf(
FormHttpMessageConverter(),
OAuth2AccessTokenResponseHttpMessageConverter()))
restTemplate.errorHandler = OAuth2ErrorResponseErrorHandler()
----
======
[TIP]
[NOTE]
====
Spring MVC `FormHttpMessageConverter` is required as it's used when sending the OAuth 2.0 Access Token Request.
This section focuses on `RestClientJwtBearerTokenResponseClient`.
You can read about {spring-security-reference-base-url}/6.3/servlet/oauth2/client/authorization-grants.html#_requesting_an_access_token_4[`DefaultClientCredentialsTokenResponseClient`] in the Spring Security 6.3 documentation.
====
`OAuth2AccessTokenResponseHttpMessageConverter` is a `HttpMessageConverter` for an OAuth 2.0 Access Token Response.
You can provide `OAuth2AccessTokenResponseHttpMessageConverter.setAccessTokenResponseConverter()` with a custom `Converter<Map<String, Object>, OAuth2AccessTokenResponse>` that is used for converting the OAuth 2.0 Access Token Response parameters to an `OAuth2AccessTokenResponse`.
:section-id: jwt-bearer
:grant-type: JWT Bearer
:class-name: RestClientJwtBearerTokenResponseClient
:grant-request: JwtBearerGrantRequest
:leveloffset: +1
include::partial$servlet/oauth2/client/rest-client-access-token-response-client.adoc[]
`OAuth2ErrorResponseErrorHandler` is a `ResponseErrorHandler` that can handle an OAuth 2.0 Error, eg. 400 Bad Request.
It uses an `OAuth2ErrorHttpMessageConverter` for converting the OAuth 2.0 Error parameters to an `OAuth2Error`.
:leveloffset: -1
Whether you customize `DefaultJwtBearerTokenResponseClient` or provide your own implementation of `OAuth2AccessTokenResponseClient`, you'll need to configure it as shown in the following example:
[[oauth2-client-jwt-bearer-authorized-client-provider-builder]]
=== Customize using the Builder
Whether you customize `RestClientJwtBearerTokenResponseClient` or provide your own implementation of `OAuth2AccessTokenResponseClient`, you can configure it using the `OAuth2AuthorizedClientProviderBuilder` (as an alternative to <<oauth2-client-jwt-bearer-access-token-response-client-bean,publishing a bean>>) as follows:
[tabs]
======
@ -1282,7 +1151,7 @@ OAuth2AuthorizedClientProvider authorizedClientProvider =
.provider(jwtBearerAuthorizedClientProvider)
.build();
...
// ...
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
----
@ -1295,18 +1164,19 @@ Kotlin::
val jwtBearerTokenResponseClient: OAuth2AccessTokenResponseClient<JwtBearerGrantRequest> = ...
val jwtBearerAuthorizedClientProvider = JwtBearerOAuth2AuthorizedClientProvider()
jwtBearerAuthorizedClientProvider.setAccessTokenResponseClient(jwtBearerTokenResponseClient);
jwtBearerAuthorizedClientProvider.setAccessTokenResponseClient(jwtBearerTokenResponseClient)
val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.provider(jwtBearerAuthorizedClientProvider)
.build()
...
// ...
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
----
======
[[oauth2-client-jwt-bearer-authorized-client-manager]]
=== Using the Access Token
Given the following Spring Boot properties for an OAuth 2.0 Client registration:
@ -1400,7 +1270,7 @@ public class OAuth2ResourceServerController {
OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest);
OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
...
// ...
}
}
@ -1423,7 +1293,7 @@ class OAuth2ResourceServerController {
val authorizedClient = authorizedClientManager.authorize(authorizeRequest)
val accessToken: OAuth2AccessToken = authorizedClient.accessToken
...
// ...
}
}
@ -1436,15 +1306,15 @@ class OAuth2ResourceServerController {
[TIP]
If you need to resolve the `Jwt` assertion from a different source, you can provide `JwtBearerOAuth2AuthorizedClientProvider.setJwtAssertionResolver()` with a custom `Function<OAuth2AuthorizationContext, Jwt>`.
[[oauth2Client-token-exchange-grant]]
== Token Exchange
[[oauth2-client-token-exchange]]
== [[oauth2Client-token-exchange-grant]]Token Exchange
[NOTE]
====
Please refer to OAuth 2.0 Token Exchange for further details on the https://datatracker.ietf.org/doc/html/rfc8693[Token Exchange] grant.
====
[[oauth2-client-token-exchange-access-token]]
=== Requesting an Access Token
[NOTE]
@ -1452,65 +1322,33 @@ Please refer to OAuth 2.0 Token Exchange for further details on the https://data
Please refer to the https://datatracker.ietf.org/doc/html/rfc8693#section-2[Token Exchange Request and Response] protocol flow for the Token Exchange grant.
====
The default implementation of `OAuth2AccessTokenResponseClient` for the Token Exchange grant is `DefaultTokenExchangeTokenResponseClient`, which uses a `RestOperations` when requesting an access token at the Authorization Servers Token Endpoint.
There are two implementations of `OAuth2AccessTokenResponseClient` that can be used to make HTTP requests to the Token Endpoint in order to obtain an access token for the Token Exchange grant:
The `DefaultTokenExchangeTokenResponseClient` is quite flexible as it allows you to customize the pre-processing of the Token Request and/or post-handling of the Token Response.
* `DefaultTokenExchangeTokenResponseClient` (_default_)
* `RestClientTokenExchangeTokenResponseClient`
The default implementation uses a `RestOperations` instance to exchange an authorization code for an access token at the Authorization Servers Token Endpoint.
Spring Security 6.4 introduces a new implementation based on `RestClient`, which provides similar functionality but is better aligned with the Reactive version of the component (based on `WebClient`) in order to provide consistent configuration for applications on either stack.
=== Customizing the Access Token Request
If you need to customize the pre-processing of the Token Request, you can provide `DefaultTokenExchangeTokenResponseClient.setRequestEntityConverter()` with a custom `Converter<TokenExchangeGrantRequest, RequestEntity<?>>`.
The default implementation `TokenExchangeGrantRequestEntityConverter` builds a `RequestEntity` representation of a https://datatracker.ietf.org/doc/html/rfc8693#section-2.1[OAuth 2.0 Access Token Request].
However, providing a custom `Converter`, would allow you to extend the Token Request and add custom parameter(s).
To customize only the parameters of the request, you can provide `TokenExchangeGrantRequestEntityConverter.setParametersConverter()` with a custom `Converter<TokenExchangeGrantRequest, MultiValueMap<String, String>>` to completely override the parameters sent with the request. This is often simpler than constructing a `RequestEntity` directly.
[TIP]
If you prefer to only add additional parameters, you can provide `TokenExchangeGrantRequestEntityConverter.addParametersConverter()` with a custom `Converter<TokenExchangeGrantRequest, MultiValueMap<String, String>>` which constructs an aggregate `Converter`.
=== Customizing the Access Token Response
On the other end, if you need to customize the post-handling of the Token Response, you will need to provide `DefaultTokenExchangeTokenResponseClient.setRestOperations()` with a custom configured `RestOperations`.
The default `RestOperations` is configured as follows:
[tabs]
======
Java::
+
[source,java,role="primary"]
----
RestTemplate restTemplate = new RestTemplate(Arrays.asList(
new FormHttpMessageConverter(),
new OAuth2AccessTokenResponseHttpMessageConverter()));
restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
----
Kotlin::
+
[source,kotlin,role="secondary"]
----
val restTemplate = RestTemplate(listOf(
FormHttpMessageConverter(),
OAuth2AccessTokenResponseHttpMessageConverter()))
restTemplate.errorHandler = OAuth2ErrorResponseErrorHandler()
----
======
[TIP]
[NOTE]
====
Spring MVC `FormHttpMessageConverter` is required as it's used when sending the OAuth 2.0 Access Token Request.
This section focuses on `RestClientTokenExchangeTokenResponseClient`.
You can read about {spring-security-reference-base-url}/6.3/servlet/oauth2/client/authorization-grants.html#_requesting_an_access_token_5[`DefaultTokenExchangeTokenResponseClient`] in the Spring Security 6.3 documentation.
====
`OAuth2AccessTokenResponseHttpMessageConverter` is a `HttpMessageConverter` for an OAuth 2.0 Access Token Response.
You can provide `OAuth2AccessTokenResponseHttpMessageConverter.setAccessTokenResponseConverter()` with a custom `Converter<Map<String, Object>, OAuth2AccessTokenResponse>` that is used for converting the OAuth 2.0 Access Token Response parameters to an `OAuth2AccessTokenResponse`.
:section-id: token-exchange
:grant-type: Token Exchange
:class-name: RestClientTokenExchangeTokenResponseClient
:grant-request: TokenExchangeGrantRequest
:leveloffset: +1
include::partial$servlet/oauth2/client/rest-client-access-token-response-client.adoc[]
`OAuth2ErrorResponseErrorHandler` is a `ResponseErrorHandler` that can handle an OAuth 2.0 Error, eg. 400 Bad Request.
It uses an `OAuth2ErrorHttpMessageConverter` for converting the OAuth 2.0 Error parameters to an `OAuth2Error`.
:leveloffset: -1
Whether you customize `DefaultTokenExchangeTokenResponseClient` or provide your own implementation of `OAuth2AccessTokenResponseClient`, you'll need to configure it as shown in the following example:
[[oauth2-client-token-exchange-authorized-client-provider-builder]]
=== Customize using the Builder
Whether you customize `RestClientTokenExchangeTokenResponseClient` or provide your own implementation of `OAuth2AccessTokenResponseClient`, you can configure it using the `OAuth2AuthorizedClientProviderBuilder` (as an alternative to <<oauth2-client-token-exchange-access-token-response-client-bean,publishing a bean>>) as follows:
[tabs]
======
@ -1529,7 +1367,7 @@ OAuth2AuthorizedClientProvider authorizedClientProvider =
.provider(tokenExchangeAuthorizedClientProvider)
.build();
...
// ...
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
----
@ -1548,14 +1386,14 @@ val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.provider(tokenExchangeAuthorizedClientProvider)
.build()
...
// ...
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
----
======
[[token-exchange-grant-access-token]]
=== Using the Access Token
[[oauth2-client-token-exchange-authorized-client-manager]]
=== [[token-exchange-grant-access-token]]Using the Access Token
Given the following Spring Boot properties for an OAuth 2.0 Client registration:
@ -1648,7 +1486,7 @@ public class OAuth2ResourceServerController {
OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest);
OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
...
// ...
}
}
@ -1671,7 +1509,7 @@ class OAuth2ResourceServerController {
val authorizedClient = authorizedClientManager.authorize(authorizeRequest)
val accessToken: OAuth2AccessToken = authorizedClient.accessToken
...
// ...
}
}

View File

@ -1,11 +1,10 @@
[[oauth2Client-additional-features]]
= Authorized Client Features
[[oauth2-client-additional-features]]
= [[oauth2Client-additional-features]]Authorized Client Features
This section covers additional features provided by Spring Security for the OAuth2 client.
[[oauth2Client-registered-authorized-client]]
== Resolving an Authorized Client
[[oauth2-client-registered-authorized-client]]
== [[oauth2Client-registered-authorized-client]]Resolving an Authorized Client
The `@RegisteredOAuth2AuthorizedClient` annotation provides the ability to resolve a method parameter to an argument value of type `OAuth2AuthorizedClient`.
This is a convenient alternative compared to accessing the `OAuth2AuthorizedClient` by using the `OAuth2AuthorizedClientManager` or `OAuth2AuthorizedClientService`.
@ -496,8 +495,8 @@ class RestClientConfig {
----
=====
[[oauth2Client-webclient-servlet]]
== WebClient Integration for Servlet Environments
[[oauth2-client-web-client]]
== [[oauth2Client-webclient-servlet]]WebClient Integration for Servlet Environments
The OAuth 2.0 Client support integrates with `WebClient` by using an `ExchangeFilterFunction`.
@ -542,6 +541,7 @@ fun webClient(authorizedClientManager: OAuth2AuthorizedClientManager?): WebClien
----
======
[[oauth2-client-web-client-authorized-client]]
=== Providing the Authorized Client
The `ServletOAuth2AuthorizedClientExchangeFilterFunction` determines the client to use (for a request) by resolving the `OAuth2AuthorizedClient` from the `ClientRequest.attributes()` (request attributes).
@ -702,7 +702,7 @@ fun index(): String {
[WARNING]
It is recommended to be cautious with this feature since all HTTP requests will receive an access token bound to the provided principal.
[[oauth2-client-web-client-default-authorized-client]]
=== 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 its configuration.

View File

@ -1,8 +1,8 @@
[[oauth2Client-client-auth-support]]
= Client Authentication Support
[[oauth2-client-authentication]]
= [[oauth2Client-client-auth-support]]Client Authentication Support
[[oauth2Client-client-credentials-auth]]
== Client Credentials
[[oauth2-client-client-credentials-authentication]]
== [[oauth2Client-client-credentials-auth]]Client Credentials
=== Authenticate using `client_secret_basic`
@ -83,8 +83,8 @@ spring:
...
----
[[oauth2Client-jwt-bearer-auth]]
== JWT Bearer
[[oauth2-client-jwt-bearer-authentication]]
== [[oauth2Client-jwt-bearer-auth]]JWT Bearer
[NOTE]
Please refer to JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication and Authorization Grants for further details on https://datatracker.ietf.org/doc/html/rfc7523#section-2.2[JWT Bearer] Client Authentication.
@ -285,8 +285,8 @@ converter.setJwtClientAssertionCustomizer { context ->
----
======
[[oauth2Client-public-auth]]
== Public Authentication
[[oauth2-client-public-authentication]]
== [[oauth2Client-public-auth]]Public Authentication
Public Client Authentication is supported out of the box and no customization is necessary to enable it.

View File

@ -1,5 +1,5 @@
[[oauth2client]]
= OAuth 2.0 Client
[[oauth2-client]]
= [[oauth2client]]OAuth 2.0 Client
:page-section-summary-toc: 1
The OAuth 2.0 Client features provide support for the Client role as defined in the https://tools.ietf.org/html/rfc6749#section-1.1[OAuth 2.0 Authorization Framework].
@ -7,19 +7,19 @@ The OAuth 2.0 Client features provide support for the Client role as defined in
At a high-level, the core features available are:
.Authorization Grant support
* https://tools.ietf.org/html/rfc6749#section-1.3.1[Authorization Code]
* https://tools.ietf.org/html/rfc6749#section-6[Refresh Token]
* https://tools.ietf.org/html/rfc6749#section-1.3.4[Client Credentials]
* https://tools.ietf.org/html/rfc6749#section-1.3.3[Resource Owner Password Credentials]
* https://datatracker.ietf.org/doc/html/rfc7523#section-2.1[JWT Bearer]
* https://datatracker.ietf.org/doc/html/rfc8693#section-2.1[Token Exchange]
* xref:servlet/oauth2/client/authorization-grants.adoc#oauth2-client-authorization-code[Authorization Code]
* xref:servlet/oauth2/client/authorization-grants.adoc#oauth2-client-refresh-token[Refresh Token]
* xref:servlet/oauth2/client/authorization-grants.adoc#oauth2-client-client-credentials[Client Credentials]
* xref:servlet/oauth2/client/authorization-grants.adoc#oauth2-client-password[Resource Owner Password Credentials]
* xref:servlet/oauth2/client/authorization-grants.adoc#oauth2-client-jwt-bearer[JWT Bearer]
* xref:servlet/oauth2/client/authorization-grants.adoc#oauth2-client-token-exchange[Token Exchange]
.Client Authentication support
* https://datatracker.ietf.org/doc/html/rfc7523#section-2.2[JWT Bearer]
* xref:servlet/oauth2/client/client-authentication.adoc#oauth2-client-jwt-bearer-authentication[JWT Bearer]
.HTTP Client support
* xref:servlet/oauth2/client/authorized-clients.adoc#oauth2-client-rest-client[`RestClient` integration] (for requesting protected resources)
* xref:servlet/oauth2/client/authorized-clients.adoc#oauth2Client-webclient-servlet[`WebClient` integration for Servlet Environments] (for requesting protected resources)
.HTTP Client support (for requesting protected resources)
* xref:servlet/oauth2/client/authorized-clients.adoc#oauth2-client-rest-client[`RestClient` integration]
* xref:servlet/oauth2/client/authorized-clients.adoc#oauth2-client-web-client[`WebClient` integration for Servlet Environments]
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.

View File

@ -0,0 +1,378 @@
To opt-in to using `{class-name}`, simply provide a bean as in the following example and it will be picked up by the default `OAuth2AuthorizedClientManager` automatically:
[#oauth2-client-{section-id}-access-token-response-client-bean]
.Access Token Response Configuration
[tabs]
======
Java::
+
[source,java,role="primary",subs="+attributes"]
----
@Bean
public OAuth2AccessTokenResponseClient<{grant-request}> accessTokenResponseClient() {
return new {class-name}();
}
----
Kotlin::
+
[source,kotlin,role="secondary",subs="+attributes"]
----
@Bean
fun myAccessTokenResponseClient(): OAuth2AccessTokenResponseClient<{grant-type}> {
return new {class-name}()
}
----
======
[NOTE]
====
The new implementation will be the default in Spring Security 7.
====
`{class-name}` is very flexible and provides several options for customizing the OAuth 2.0 Access Token request and response for the {grant-type} grant.
Choose from the following use cases to learn more:
* I want to <<oauth2-client-{section-id}-access-token-request-headers,customize headers of the Access Token request>>
* I want to <<oauth2-client-{section-id}-access-token-request-parameters,customize parameters of the Access Token request>>
* I want to <<oauth2-client-{section-id}-access-token-response,customize the instance of `RestClient` that is used>>
* I want to <<oauth2-client-{section-id}-access-token-response-parameters,customize parameters of the Access Token response>>
* I want to <<oauth2-client-{section-id}-access-token-response-errors,customize error handling of the Access Token response>>
[#oauth2-client-{section-id}-access-token-request]
== Customizing the Access Token Request
`{class-name}` provides hooks for customizing HTTP headers and request parameters of the Token Request.
[#oauth2-client-{section-id}-access-token-request-headers]
=== Customizing Request Headers
There are two options for customizing HTTP headers by providing a `Converter<{grant-request}, HttpHeaders>`:
* Add additional headers by calling `addHeadersConverter(...)`
* Fully customize headers by calling `setHeadersConverter(...)`
You can include additional headers without affecting the default headers added to every request using `addHeadersConverter()`.
The following example adds a `User-Agent` header to the request when the `registrationId` is `spring`:
.Include Additional HTTP Headers
[tabs]
======
Java::
+
[source,java,role="primary",subs="+attributes"]
----
{class-name} accessTokenResponseClient =
new {class-name}();
accessTokenResponseClient.addHeadersConverter((grantRequest) -> {
ClientRegistration clientRegistration = grantRequest.getClientRegistration();
HttpHeaders headers = new HttpHeaders();
if (clientRegistration.getRegistrationId().equals("spring")) {
headers.set(HttpHeaders.USER_AGENT, "...");
}
return headers;
});
----
Kotlin::
+
[source,kotlin,role="secondary",subs="+attributes"]
----
val accessTokenResponseClient = {class-name}()
accessTokenResponseClient.addHeadersConverter { grantRequest ->
val clientRegistration = grantRequest.getClientRegistration()
val headers = HttpHeaders()
if (clientRegistration.getRegistrationId() == "spring") {
headers[HttpHeaders.USER_AGENT] = "..."
}
headers
}
----
======
You can fully customize headers by re-using `DefaultOAuth2TokenRequestHeadersConverter` or providing a custom implementation using `setHeadersConverter()`.
The following example re-uses `DefaultOAuth2TokenRequestHeadersConverter` and disables `encodeClientCredentials` so that HTTP Basic credentials are no longer encoded with `application/x-www-form-urlencoded`:
.Customize HTTP Headers
[tabs]
======
Java::
+
[source,java,role="primary",subs="+attributes"]
----
DefaultOAuth2TokenRequestHeadersConverter headersConverter =
new DefaultOAuth2TokenRequestHeadersConverter();
headersConverter.setEncodeClientCredentials(false);
{class-name} accessTokenResponseClient =
new {class-name}();
accessTokenResponseClient.setHeadersConverter(headersConverter);
----
Kotlin::
+
[source,kotlin,role="secondary",subs="+attributes"]
----
val headersConverter = DefaultOAuth2TokenRequestHeadersConverter()
headersConverter.setEncodeClientCredentials(false)
val accessTokenResponseClient = {class-name}()
accessTokenResponseClient.setHeadersConverter(headersConverter)
----
======
[#oauth2-client-{section-id}-access-token-request-parameters]
=== Customizing Request Parameters
There are two options for customizing request parameters by providing a `Converter<{grant-request}, MultiValueMap<String, String>>`:
* Add additional parameters by calling `addParametersConverter(...)`
* Override parameters by calling `setParametersConverter(...)`
[NOTE]
====
Using `setParametersConverter()` does not fully customize parameters because it would require the user to provide all default parameters themselves.
Default parameters are always provided, but can be fully customized or omitted by providing a `Consumer<MultiValueMap<String, String>>` to `setParametersCustomizer(...)`.
====
You can include additional parameters without affecting the default parameters added to every request using `addParametersConverter()`.
The following example adds an `audience` parameter to the request when the `registrationId` is `keycloak`:
.Include Additional Request Parameters
[tabs]
======
Java::
+
[source,java,role="primary",subs="+attributes"]
----
{class-name} accessTokenResponseClient =
new {class-name}();
accessTokenResponseClient.addParametersConverter((grantRequest) -> {
ClientRegistration clientRegistration = grantRequest.getClientRegistration();
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
if (clientRegistration.getRegistrationId().equals("keycloak")) {
parameters.set(OAuth2ParameterNames.AUDIENCE, "my-audience");
}
return parameters;
});
----
Kotlin::
+
[source,kotlin,role="secondary",subs="+attributes"]
----
val accessTokenResponseClient = {class-name}()
accessTokenResponseClient.addParametersConverter { grantRequest ->
val clientRegistration = grantRequest.getClientRegistration()
val parameters = LinkedMultiValueMap<String, String>()
if (clientRegistration.getRegistrationId() == "keycloak") {
parameters[OAuth2ParameterNames.AUDIENCE] = "my-audience"
}
parameters
}
----
======
You can override default parameters using `setParametersConverter()`.
The following example overrides the `client_id` parameter when the `registrationId` is `okta`:
.Override Request Parameters
[tabs]
======
Java::
+
[source,java,role="primary",subs="+attributes"]
----
{class-name} accessTokenResponseClient =
new {class-name}();
accessTokenResponseClient.setParametersConverter((grantRequest) -> {
ClientRegistration clientRegistration = grantRequest.getClientRegistration();
LinkedMultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
if (clientRegistration.getRegistrationId().equals("okta")) {
parameters.set(OAuth2ParameterNames.CLIENT_ID, "my-client");
}
return parameters;
});
----
Kotlin::
+
[source,kotlin,role="secondary",subs="+attributes"]
----
val parametersConverter = DefaultOAuth2TokenRequestParametersConverter<{grant-request}>()
parametersConverter.setParametersCustomizer { parameters ->
if (parameters.containsKey(OAuth2ParameterNames.CLIENT_ASSERTION)) {
parameters.remove(OAuth2ParameterNames.CLIENT_ID)
}
}
val accessTokenResponseClient = {class-name}()
accessTokenResponseClient.setParametersConverter { grantRequest ->
val clientRegistration = grantRequest.getClientRegistration()
val parameters = LinkedMultiValueMap<String, String>()
if (clientRegistration.getRegistrationId() == "okta") {
parameters[OAuth2ParameterNames.CLIENT_ID] = "my-client"
}
parameters
}
----
======
You can fully customize parameters (including omitting default parameters) using `setParametersCustomizer()`.
The following example omits the `client_id` parameter when the `client_assertion` parameter is present in the request:
.Omit Request Parameters
[tabs]
======
Java::
+
[source,java,role="primary",subs="+attributes"]
----
{class-name} accessTokenResponseClient =
new {class-name}();
accessTokenResponseClient.setParametersCustomizer((parameters) -> {
if (parameters.containsKey(OAuth2ParameterNames.CLIENT_ASSERTION)) {
parameters.remove(OAuth2ParameterNames.CLIENT_ID);
}
});
----
Kotlin::
+
[source,kotlin,role="secondary",subs="+attributes"]
----
val accessTokenResponseClient = {class-name}()
accessTokenResponseClient.setParametersCustomizer { parameters ->
if (parameters.containsKey(OAuth2ParameterNames.CLIENT_ASSERTION)) {
parameters.remove(OAuth2ParameterNames.CLIENT_ID)
}
}
----
======
[#oauth2-client-{section-id}-access-token-response]
== Customizing the Access Token Response
You can customize the Token Response by providing a pre-configured `RestClient` to `setRestClient(...)`.
The default `RestClient` is configured as follows:
.Default `RestClient` Configuration
[tabs]
======
Java::
+
[source,java,role="primary",subs="+attributes"]
----
RestClient restClient = RestClient.builder()
.messageConverters((messageConverters) -> {
messageConverters.clear();
messageConverters.add(new FormHttpMessageConverter());
messageConverters.add(new OAuth2AccessTokenResponseHttpMessageConverter());
})
.defaultStatusHandler(new OAuth2ErrorResponseErrorHandler())
.build();
{class-name} accessTokenResponseClient =
new {class-name}();
accessTokenResponseClient.setRestClient(restClient);
----
Kotlin::
+
[source,kotlin,role="secondary",subs="+attributes"]
----
val restClient = RestClient.builder()
.messageConverters { messageConverters ->
messageConverters.clear()
messageConverters.add(FormHttpMessageConverter())
messageConverters.add(OAuth2AccessTokenResponseHttpMessageConverter())
}
.defaultStatusHandler(OAuth2ErrorResponseErrorHandler())
.build()
val accessTokenResponseClient = {class-name}()
accessTokenResponseClient.setRestClient(restClient)
----
======
`OAuth2AccessTokenResponseHttpMessageConverter` is an `HttpMessageConverter` for an OAuth 2.0 Access Token Response.
You can provide `setAccessTokenResponseConverter()` with a custom `Converter<Map<String, Object>, OAuth2AccessTokenResponse>` that is used for converting the OAuth 2.0 Access Token Response parameters to an `OAuth2AccessTokenResponse`.
`OAuth2ErrorResponseErrorHandler` is a `ResponseErrorHandler` that can handle an OAuth 2.0 Error, such as `400 Bad Request`.
It uses an `OAuth2ErrorHttpMessageConverter` for converting the OAuth 2.0 Error parameters to an `OAuth2Error`.
[TIP]
====
Spring MVC `FormHttpMessageConverter` is required, as it is used when sending the OAuth 2.0 Access Token Request.
====
[#oauth2-client-{section-id}-access-token-response-parameters]
The following example provides a starting point for customizing the conversion of Token Response parameters to an `OAuth2AccessTokenResponse`:
.Customize Access Token Response Converter
[tabs]
======
Java::
+
[source,java,role="primary"]
----
OAuth2AccessTokenResponseHttpMessageConverter accessTokenResponseMessageConverter =
new OAuth2AccessTokenResponseHttpMessageConverter();
accessTokenResponseMessageConverter.setAccessTokenResponseConverter((parameters) -> {
// ...
return OAuth2AccessTokenResponse.withToken("custom-token")
// ...
.build();
});
----
Kotlin::
+
[source,kotlin,role="secondary"]
----
val accessTokenResponseMessageConverter = OAuth2AccessTokenResponseHttpMessageConverter()
accessTokenResponseMessageConverter.setAccessTokenResponseConverter { parameters ->
// ...
return OAuth2AccessTokenResponse.withToken("custom-token")
// ...
.build()
}
----
======
[#oauth2-client-{section-id}-access-token-response-errors]
The following example provides a starting point for customizing the conversion of Error parameters to an `OAuth2Error`:
.Customize Access Token Error Handler
[tabs]
======
Java::
+
[source,java,role="primary"]
----
OAuth2ErrorHttpMessageConverter errorConverter =
new OAuth2ErrorHttpMessageConverter();
errorConverter.setErrorConverter((parameters) -> {
// ...
return new OAuth2Error("custom-error", "custom description", "custom-uri");
});
OAuth2ErrorResponseErrorHandler errorHandler =
new OAuth2ErrorResponseErrorHandler();
errorHandler.setErrorConverter(errorConverter);
----
Kotlin::
+
[source,kotlin,role="secondary"]
----
val errorConverter = OAuth2ErrorHttpMessageConverter()
errorConverter.setErrorConverter { parameters ->
// ...
return OAuth2Error("custom-error", "custom description", "custom-uri")
}
val errorHandler = OAuth2ErrorResponseErrorHandler()
errorHandler.setErrorConverter(errorConverter)
----
======