Document RestClient-based implementations
Closes gh-15938
This commit is contained in:
parent
d0fc4fe4dc
commit
8982851355
|
@ -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 Server’s 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 Server’s 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 Server’s 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 Server’s 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 Server’s 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 Server’s 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 Server’s 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 Server’s 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 Server’s 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 Server’s 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 Server’s 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
|
||||
|
||||
...
|
||||
// ...
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
----
|
||||
======
|
Loading…
Reference in New Issue