From ea5bc28773b45e62fe83739dc62b81d5229b4ad3 Mon Sep 17 00:00:00 2001 From: Steve Riesenberg <5248162+sjohnr@users.noreply.github.com> Date: Mon, 28 Oct 2024 12:28:24 -0500 Subject: [PATCH] Polish OAuth2 docs --- .../oauth2/client/authorization-grants.adoc | 59 ++++++++++++++++++- .../oauth2/client/authorized-clients.adoc | 4 ++ .../oauth2/client/client-authentication.adoc | 4 ++ .../pages/reactive/oauth2/client/core.adoc | 8 +++ .../oauth2/client/authorization-grants.adoc | 19 +++++- .../oauth2/client/authorized-clients.adoc | 4 +- .../oauth2/client/client-authentication.adoc | 16 +++-- .../pages/servlet/oauth2/client/index.adoc | 2 +- .../ROOT/pages/servlet/oauth2/index.adoc | 2 +- ...t-client-access-token-response-client.adoc | 56 +++++++++++------- 10 files changed, 142 insertions(+), 32 deletions(-) diff --git a/docs/modules/ROOT/pages/reactive/oauth2/client/authorization-grants.adoc b/docs/modules/ROOT/pages/reactive/oauth2/client/authorization-grants.adoc index 04a3e96e4d..bd002f31e8 100644 --- a/docs/modules/ROOT/pages/reactive/oauth2/client/authorization-grants.adoc +++ b/docs/modules/ROOT/pages/reactive/oauth2/client/authorization-grants.adoc @@ -7,13 +7,17 @@ This section describes Spring Security's support for authorization grants. == [[oauth2Client-auth-code-grant]]Authorization Code [NOTE] +==== Please refer to 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] +==== Please refer to 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 @@ -47,8 +51,10 @@ spring: A request with the base path `/oauth2/authorization/okta` will initiate the Authorization Request redirect by the `OAuth2AuthorizationRequestRedirectWebFilter` and ultimately start the Authorization Code grant flow. [NOTE] +==== The `AuthorizationCodeReactiveOAuth2AuthorizedClientProvider` is an implementation of `ReactiveOAuth2AuthorizedClientProvider` for the Authorization Code grant, which also initiates the Authorization Request redirect by the `OAuth2AuthorizationRequestRedirectWebFilter`. +==== If the OAuth 2.0 Client is a https://tools.ietf.org/html/rfc6749#section-2.1[Public Client], then configure the OAuth 2.0 Client registration as follows: @@ -74,7 +80,9 @@ If the client is running in an untrusted environment (eg. native application or . `client-authentication-method` is set to "none" (`ClientAuthenticationMethod.NONE`) [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 `DefaultServerOAuth2AuthorizationRequestResolver.setAuthorizationRequestCustomizer(OAuth2AuthorizationRequestCustomizers.withPkce())`. +==== [[oauth2-client-authorization-code-redirect-uri]] [[oauth2Client-auth-code-redirect-uri]]The `DefaultServerOAuth2AuthorizationRequestResolver` also supports `URI` template variables for the `redirect-uri` using `UriComponentsBuilder`. @@ -95,7 +103,9 @@ spring: ---- [NOTE] +==== `+{baseUrl}+` resolves to `+{baseScheme}://{baseHost}{basePort}{basePath}+` +==== 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]. This ensures that the `X-Forwarded-*` headers are used when expanding the `redirect-uri`. @@ -224,7 +234,9 @@ The preceding example shows the common use case of adding a custom parameter on Alternatively, if your requirements are more advanced, you can take full control in building the Authorization Request URI by simply overriding the `OAuth2AuthorizationRequest.authorizationRequestUri` property. [TIP] +==== `OAuth2AuthorizationRequest.Builder.build()` constructs the `OAuth2AuthorizationRequest.authorizationRequestUri`, which represents the Authorization Request URI including all query parameters using the `application/x-www-form-urlencoded` format. +==== The following example shows a variation of `authorizationRequestCustomizer()` from the preceding example, and instead overrides the `OAuth2AuthorizationRequest.authorizationRequestUri` property. @@ -263,7 +275,9 @@ private fun authorizationRequestCustomizer(): Consumer>`. +==== [[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] +==== 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 `ReactiveOAuth2AccessTokenResponseClient` for the Token Exchange grant is `WebClientReactiveTokenExchangeTokenResponseClient`, which uses a `WebClient` when requesting an access token at the Authorization Server’s Token Endpoint. @@ -1308,11 +1357,17 @@ class OAuth2ResourceServerController { ====== [NOTE] +==== `TokenExchangeReactiveOAuth2AuthorizedClientProvider` resolves the subject token (as an `OAuth2Token`) via `OAuth2AuthorizationContext.getPrincipal().getPrincipal()` by default, hence the use of `JwtAuthenticationToken` in the preceding example. An actor token is not resolved by default. +==== [TIP] +==== If you need to resolve the subject token from a different source, you can provide `TokenExchangeReactiveOAuth2AuthorizedClientProvider.setSubjectTokenResolver()` with a custom `Function>`. +==== [TIP] +==== If you need to resolve an actor token, you can provide `TokenExchangeReactiveOAuth2AuthorizedClientProvider.setActorTokenResolver()` with a custom `Function>`. +==== diff --git a/docs/modules/ROOT/pages/reactive/oauth2/client/authorized-clients.adoc b/docs/modules/ROOT/pages/reactive/oauth2/client/authorized-clients.adoc index 1352c7c20b..42391468b3 100644 --- a/docs/modules/ROOT/pages/reactive/oauth2/client/authorized-clients.adoc +++ b/docs/modules/ROOT/pages/reactive/oauth2/client/authorized-clients.adoc @@ -227,7 +227,9 @@ fun webClient(authorizedClientManager: ReactiveOAuth2AuthorizedClientManager): W ====== [WARNING] +==== It is recommended to be cautious with this feature since all HTTP requests will receive the access token. +==== Alternatively, if `setDefaultClientRegistrationId("okta")` is configured with a valid `ClientRegistration`, the `OAuth2AccessToken` associated with the `OAuth2AuthorizedClient` is used. @@ -266,4 +268,6 @@ fun webClient(authorizedClientManager: ReactiveOAuth2AuthorizedClientManager): W ====== [WARNING] +==== It is recommended to be cautious with this feature since all HTTP requests will receive the access token. +==== diff --git a/docs/modules/ROOT/pages/reactive/oauth2/client/client-authentication.adoc b/docs/modules/ROOT/pages/reactive/oauth2/client/client-authentication.adoc index 053552ab74..f6d5107969 100644 --- a/docs/modules/ROOT/pages/reactive/oauth2/client/client-authentication.adoc +++ b/docs/modules/ROOT/pages/reactive/oauth2/client/client-authentication.adoc @@ -82,7 +82,9 @@ spring: == [[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. +==== The default implementation for JWT Bearer Client Authentication is `NimbusJwtClientAuthenticationParametersConverter`, which is a `Converter` that customizes the Token Request parameters by adding @@ -290,5 +292,7 @@ spring: ---- [NOTE] +==== Public Clients are supported using https://tools.ietf.org/html/rfc7636[Proof Key for Code Exchange] (PKCE). PKCE will automatically be used when `client-authentication-method` is set to "none" (`ClientAuthenticationMethod.NONE`). +==== diff --git a/docs/modules/ROOT/pages/reactive/oauth2/client/core.adoc b/docs/modules/ROOT/pages/reactive/oauth2/client/core.adoc index 25b2d2b7fb..b6eee52585 100644 --- a/docs/modules/ROOT/pages/reactive/oauth2/client/core.adoc +++ b/docs/modules/ROOT/pages/reactive/oauth2/client/core.adoc @@ -97,13 +97,17 @@ As an alternative, you can use `ClientRegistrations.fromOidcIssuerLocation()` to The `ReactiveClientRegistrationRepository` serves as a repository for OAuth 2.0 / OpenID Connect 1.0 `ClientRegistration`(s). [NOTE] +==== Client registration information is ultimately stored and owned by the associated Authorization Server. This repository provides the ability to retrieve a sub-set of the primary client registration information, which is stored with the Authorization Server. +==== Spring Boot auto-configuration binds each of the properties under `spring.security.oauth2.client.registration._[registrationId]_` to an instance of `ClientRegistration` and then composes each of the `ClientRegistration` instance(s) within a `ReactiveClientRegistrationRepository`. [NOTE] +==== The default implementation of `ReactiveClientRegistrationRepository` is `InMemoryReactiveClientRegistrationRepository`. +==== The auto-configuration also registers the `ReactiveClientRegistrationRepository` as a `@Bean` in the `ApplicationContext` so that it is available for dependency-injection, if needed by the application. @@ -213,15 +217,19 @@ class OAuth2ClientController { ====== [NOTE] +==== Spring Boot auto-configuration registers an `ServerOAuth2AuthorizedClientRepository` and/or `ReactiveOAuth2AuthorizedClientService` `@Bean` in the `ApplicationContext`. However, the application may choose to override and register a custom `ServerOAuth2AuthorizedClientRepository` or `ReactiveOAuth2AuthorizedClientService` `@Bean`. +==== The default implementation of `ReactiveOAuth2AuthorizedClientService` is `InMemoryReactiveOAuth2AuthorizedClientService`, which stores `OAuth2AuthorizedClient`(s) in-memory. Alternatively, the R2DBC implementation `R2dbcReactiveOAuth2AuthorizedClientService` may be configured for persisting `OAuth2AuthorizedClient`(s) in a database. [NOTE] +==== `R2dbcReactiveOAuth2AuthorizedClientService` depends on the table definition described in xref:servlet/appendix/database-schema.adoc#dbschema-oauth2-client[ OAuth 2.0 Client Schema]. +==== [[oauth2Client-authorized-manager-provider]] diff --git a/docs/modules/ROOT/pages/servlet/oauth2/client/authorization-grants.adoc b/docs/modules/ROOT/pages/servlet/oauth2/client/authorization-grants.adoc index 5d248a1e70..4cab6a8472 100644 --- a/docs/modules/ROOT/pages/servlet/oauth2/client/authorization-grants.adoc +++ b/docs/modules/ROOT/pages/servlet/oauth2/client/authorization-grants.adoc @@ -81,7 +81,9 @@ If the client is running in an untrusted environment (such as a native applicati . `client-authentication-method` is set to `none` (`ClientAuthenticationMethod.NONE`) [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())`. +==== [[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`. @@ -494,6 +496,7 @@ include::partial$servlet/oauth2/client/rest-client-access-token-response-client. Whether you customize `RestClientRefreshTokenTokenResponseClient` or provide your own implementation of `OAuth2AccessTokenResponseClient`, you can configure it using the `OAuth2AuthorizedClientProviderBuilder` (as an alternative to <>) as follows: +.Access Token Response Configuration via Builder [tabs] ====== Java:: @@ -554,7 +557,7 @@ Please refer to the OAuth 2.0 Authorization Framework for further details on the [NOTE] ==== -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. +See the https://tools.ietf.org/html/rfc6749#section-4.4.2[Access Token Request/Response] protocol flow for the Client Credentials grant. ==== 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: @@ -585,6 +588,7 @@ include::partial$servlet/oauth2/client/rest-client-access-token-response-client. Whether you customize `RestClientClientCredentialsTokenResponseClient` or provide your own implementation of `OAuth2AccessTokenResponseClient`, you can configure it using the `OAuth2AuthorizedClientProviderBuilder` (as an alternative to <>) as follows: +.Access Token Response Configuration via Builder [tabs] ====== Java:: @@ -861,6 +865,7 @@ It uses an `OAuth2ErrorHttpMessageConverter` to convert the OAuth 2.0 Error para Whether you customize `DefaultPasswordTokenResponseClient` or provide your own implementation of `OAuth2AccessTokenResponseClient`, you need to configure it as follows: +.Access Token Response Configuration via Builder [tabs] ====== Java:: @@ -1134,6 +1139,7 @@ include::partial$servlet/oauth2/client/rest-client-access-token-response-client. Whether you customize `RestClientJwtBearerTokenResponseClient` or provide your own implementation of `OAuth2AccessTokenResponseClient`, you can configure it using the `OAuth2AuthorizedClientProviderBuilder` (as an alternative to <>) as follows: +.Access Token Response Configuration via Builder [tabs] ====== Java:: @@ -1301,10 +1307,14 @@ class OAuth2ResourceServerController { ====== [NOTE] +==== `JwtBearerOAuth2AuthorizedClientProvider` resolves the `Jwt` assertion via `OAuth2AuthorizationContext.getPrincipal().getPrincipal()` by default, hence the use of `JwtAuthenticationToken` in the preceding example. +==== [TIP] +==== If you need to resolve the `Jwt` assertion from a different source, you can provide `JwtBearerOAuth2AuthorizedClientProvider.setJwtAssertionResolver()` with a custom `Function`. +==== [[oauth2-client-token-exchange]] == [[oauth2Client-token-exchange-grant]]Token Exchange @@ -1350,6 +1360,7 @@ include::partial$servlet/oauth2/client/rest-client-access-token-response-client. Whether you customize `RestClientTokenExchangeTokenResponseClient` or provide your own implementation of `OAuth2AccessTokenResponseClient`, you can configure it using the `OAuth2AuthorizedClientProviderBuilder` (as an alternative to <>) as follows: +.Access Token Response Configuration via Builder [tabs] ====== Java:: @@ -1517,11 +1528,17 @@ class OAuth2ResourceServerController { ====== [NOTE] +==== `TokenExchangeOAuth2AuthorizedClientProvider` resolves the subject token (as an `OAuth2Token`) via `OAuth2AuthorizationContext.getPrincipal().getPrincipal()` by default, hence the use of `JwtAuthenticationToken` in the preceding example. An actor token is not resolved by default. +==== [TIP] +==== If you need to resolve the subject token from a different source, you can provide `TokenExchangeOAuth2AuthorizedClientProvider.setSubjectTokenResolver()` with a custom `Function`. +==== [TIP] +==== If you need to resolve an actor token, you can provide `TokenExchangeOAuth2AuthorizedClientProvider.setActorTokenResolver()` with a custom `Function`. +==== diff --git a/docs/modules/ROOT/pages/servlet/oauth2/client/authorized-clients.adoc b/docs/modules/ROOT/pages/servlet/oauth2/client/authorized-clients.adoc index 4ced96eeb3..8864e4e7db 100644 --- a/docs/modules/ROOT/pages/servlet/oauth2/client/authorized-clients.adoc +++ b/docs/modules/ROOT/pages/servlet/oauth2/client/authorized-clients.adoc @@ -1,7 +1,7 @@ [[oauth2-client-additional-features]] = [[oauth2Client-additional-features]]Authorized Client Features -This section covers additional features provided by Spring Security for the OAuth2 client. +This section covers additional features provided by Spring Security for OAuth2 client. [[oauth2-client-registered-authorized-client]] == [[oauth2Client-registered-authorized-client]]Resolving an Authorized Client @@ -700,7 +700,9 @@ fun index(): String { <1> `authentication()` is a `static` method in `ServletOAuth2AuthorizedClientExchangeFilterFunction`. [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 diff --git a/docs/modules/ROOT/pages/servlet/oauth2/client/client-authentication.adoc b/docs/modules/ROOT/pages/servlet/oauth2/client/client-authentication.adoc index 85eb84b2e4..62197146c2 100644 --- a/docs/modules/ROOT/pages/servlet/oauth2/client/client-authentication.adoc +++ b/docs/modules/ROOT/pages/servlet/oauth2/client/client-authentication.adoc @@ -1,9 +1,10 @@ [[oauth2-client-authentication]] = [[oauth2Client-client-auth-support]]Client Authentication Support -[[oauth2-client-client-credentials-authentication]] +[[oauth2-client-authentication-client-credentials]] == [[oauth2Client-client-credentials-auth]]Client Credentials +[[oauth2-client-authentication-client-credentials-client-secret-basic]] === Authenticate using `client_secret_basic` Client Authentication with HTTP Basic is supported out of the box and no customization is necessary to enable it. @@ -62,6 +63,7 @@ tokenResponseClient.setRequestEntityConverter(requestEntityConverter) ---- ====== +[[oauth2-client-authentication-client-credentials-client-secret-post]] === Authenticate using `client_secret_post` Client Authentication with client credentials included in the request-body is supported out of the box and no customization is necessary to enable it. @@ -83,11 +85,13 @@ spring: ... ---- -[[oauth2-client-jwt-bearer-authentication]] +[[oauth2-client-authentication-jwt-bearer]] == [[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. +==== The default implementation for JWT Bearer Client Authentication is `NimbusJwtClientAuthenticationParametersConverter`, which is a `Converter` that customizes the Token Request parameters by adding @@ -96,7 +100,7 @@ a signed JSON Web Token (JWS) in the `client_assertion` parameter. The `java.security.PrivateKey` or `javax.crypto.SecretKey` used for signing the JWS is supplied by the `com.nimbusds.jose.jwk.JWK` resolver associated with `NimbusJwtClientAuthenticationParametersConverter`. - +[[oauth2-client-authentication-jwt-bearer-private-key-jwt]] === Authenticate using `private_key_jwt` Given the following Spring Boot properties for an OAuth 2.0 Client registration: @@ -174,6 +178,7 @@ tokenResponseClient.setRequestEntityConverter(requestEntityConverter) ---- ====== +[[oauth2-client-authentication-jwt-bearer-client-secret-jwt]] === Authenticate using `client_secret_jwt` Given the following Spring Boot properties for an OAuth 2.0 Client registration: @@ -250,6 +255,7 @@ tokenResponseClient.setRequestEntityConverter(requestEntityConverter) ---- ====== +[[oauth2-client-authentication-jwt-bearer-assertion]] === Customizing the JWT assertion The JWT produced by `NimbusJwtClientAuthenticationParametersConverter` contains the `iss`, `sub`, `aud`, `jti`, `iat` and `exp` claims by default. You can customize the headers and/or claims by providing a `Consumer>` to `setJwtClientAssertionCustomizer()`. The following example shows how to customize claims of the JWT: @@ -285,7 +291,7 @@ converter.setJwtClientAssertionCustomizer { context -> ---- ====== -[[oauth2-client-public-authentication]] +[[oauth2-client-authentication-public]] == [[oauth2Client-public-auth]]Public Authentication Public Client Authentication is supported out of the box and no customization is necessary to enable it. @@ -307,5 +313,7 @@ spring: ---- [NOTE] +==== Public Clients are supported using https://tools.ietf.org/html/rfc7636[Proof Key for Code Exchange] (PKCE). PKCE will automatically be used when `client-authentication-method` is set to "none" (`ClientAuthenticationMethod.NONE`). +==== diff --git a/docs/modules/ROOT/pages/servlet/oauth2/client/index.adoc b/docs/modules/ROOT/pages/servlet/oauth2/client/index.adoc index da239d1b57..e4195ea9dc 100644 --- a/docs/modules/ROOT/pages/servlet/oauth2/client/index.adoc +++ b/docs/modules/ROOT/pages/servlet/oauth2/client/index.adoc @@ -15,7 +15,7 @@ At a high-level, the core features available are: * xref:servlet/oauth2/client/authorization-grants.adoc#oauth2-client-token-exchange[Token Exchange] .Client Authentication support -* xref:servlet/oauth2/client/client-authentication.adoc#oauth2-client-jwt-bearer-authentication[JWT Bearer] +* xref:servlet/oauth2/client/client-authentication.adoc#oauth2-client-authentication-jwt-bearer[JWT Bearer] .HTTP Client support (for requesting protected resources) * xref:servlet/oauth2/client/authorized-clients.adoc#oauth2-client-rest-client[`RestClient` integration] diff --git a/docs/modules/ROOT/pages/servlet/oauth2/index.adoc b/docs/modules/ROOT/pages/servlet/oauth2/index.adoc index 5207c9c15f..422a73bbcc 100644 --- a/docs/modules/ROOT/pages/servlet/oauth2/index.adoc +++ b/docs/modules/ROOT/pages/servlet/oauth2/index.adoc @@ -2059,7 +2059,7 @@ class SecurityConfig { [[further-reading]] == Further Reading -This preceding sections introduced Spring Security's support for OAuth2 with examples for common scenarios. +The preceding sections introduced Spring Security's support for OAuth2 with examples for common scenarios. You can read more about OAuth2 Client and Resource Server in the following sections of the reference documentation: * xref:servlet/oauth2/login/index.adoc[] diff --git a/docs/modules/ROOT/partials/servlet/oauth2/client/rest-client-access-token-response-client.adoc b/docs/modules/ROOT/partials/servlet/oauth2/client/rest-client-access-token-response-client.adoc index 60377fa4a8..94941fcd58 100644 --- a/docs/modules/ROOT/partials/servlet/oauth2/client/rest-client-access-token-response-client.adoc +++ b/docs/modules/ROOT/partials/servlet/oauth2/client/rest-client-access-token-response-client.adoc @@ -19,8 +19,8 @@ Kotlin:: [source,kotlin,role="secondary",subs="+attributes"] ---- @Bean -fun myAccessTokenResponseClient(): OAuth2AccessTokenResponseClient<{grant-type}> { - return new {class-name}() +fun accessTokenResponseClient(): OAuth2AccessTokenResponseClient<{grant-type}> { + return {class-name}() } ---- ====== @@ -35,22 +35,22 @@ Choose from the following use cases to learn more: * I want to <> * I want to <> -* I want to <> +* I want to <> * I want to <> * I want to <> [#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. +`{class-name}` provides hooks for customizing HTTP headers and request parameters of the OAuth 2.0 Access 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>`: +There are two options for customizing HTTP headers: -* Add additional headers by calling `addHeadersConverter(...)` -* Fully customize headers by calling `setHeadersConverter(...)` +* 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`: @@ -64,11 +64,11 @@ Java:: ---- {class-name} accessTokenResponseClient = new {class-name}(); -accessTokenResponseClient.addHeadersConverter((grantRequest) -> { +accessTokenResponseClient.addHeadersConverter(grantRequest -> { ClientRegistration clientRegistration = grantRequest.getClientRegistration(); HttpHeaders headers = new HttpHeaders(); if (clientRegistration.getRegistrationId().equals("spring")) { - headers.set(HttpHeaders.USER_AGENT, "..."); + headers.set(HttpHeaders.USER_AGENT, "my-user-agent"); } return headers; }); @@ -83,7 +83,7 @@ accessTokenResponseClient.addHeadersConverter { grantRequest -> val clientRegistration = grantRequest.getClientRegistration() val headers = HttpHeaders() if (clientRegistration.getRegistrationId() == "spring") { - headers[HttpHeaders.USER_AGENT] = "..." + headers[HttpHeaders.USER_AGENT] = "my-user-agent" } headers } @@ -124,15 +124,16 @@ 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>`: +There are three options for customizing request parameters: -* Add additional parameters by calling `addParametersConverter(...)` -* Override parameters by calling `setParametersConverter(...)` +* Add additional parameters by calling `addParametersConverter()` +* Override parameters by calling `setParametersConverter()` +* Fully customize parameters by calling `setParametersCustomizer()` [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>` to `setParametersCustomizer(...)`. +Default parameters are always provided, but can be fully customized or omitted by calling `setParametersCustomizer()`. ==== You can include additional parameters without affecting the default parameters added to every request using `addParametersConverter()`. @@ -147,7 +148,7 @@ Java:: ---- {class-name} accessTokenResponseClient = new {class-name}(); -accessTokenResponseClient.addParametersConverter((grantRequest) -> { +accessTokenResponseClient.addParametersConverter(grantRequest -> { ClientRegistration clientRegistration = grantRequest.getClientRegistration(); MultiValueMap parameters = new LinkedMultiValueMap(); if (clientRegistration.getRegistrationId().equals("keycloak")) { @@ -185,7 +186,7 @@ Java:: ---- {class-name} accessTokenResponseClient = new {class-name}(); -accessTokenResponseClient.setParametersConverter((grantRequest) -> { +accessTokenResponseClient.setParametersConverter(grantRequest -> { ClientRegistration clientRegistration = grantRequest.getClientRegistration(); LinkedMultiValueMap parameters = new LinkedMultiValueMap<>(); if (clientRegistration.getRegistrationId().equals("okta")) { @@ -230,7 +231,7 @@ Java:: ---- {class-name} accessTokenResponseClient = new {class-name}(); -accessTokenResponseClient.setParametersCustomizer((parameters) -> { +accessTokenResponseClient.setParametersCustomizer(parameters -> { if (parameters.containsKey(OAuth2ParameterNames.CLIENT_ASSERTION)) { parameters.remove(OAuth2ParameterNames.CLIENT_ID); } @@ -253,7 +254,12 @@ accessTokenResponseClient.setParametersCustomizer { parameters -> [#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(...)`. +`{class-name}` provides hooks for customizing response parameters and error handling of the OAuth 2.0 Access Token Response. + +[#oauth2-client-{section-id}-access-token-response-rest-client] +=== Customizing the `WebClient` + +You can customize the Token Response by providing a pre-configured `RestClient` to `setRestClient()`. The default `RestClient` is configured as follows: .Default `RestClient` Configuration @@ -264,7 +270,7 @@ Java:: [source,java,role="primary",subs="+attributes"] ---- RestClient restClient = RestClient.builder() - .messageConverters((messageConverters) -> { + .messageConverters(messageConverters -> { messageConverters.clear(); messageConverters.add(new FormHttpMessageConverter()); messageConverters.add(new OAuth2AccessTokenResponseHttpMessageConverter()); @@ -296,10 +302,12 @@ accessTokenResponseClient.setRestClient(restClient) ====== `OAuth2AccessTokenResponseHttpMessageConverter` is an `HttpMessageConverter` for an OAuth 2.0 Access Token Response. -You can provide `setAccessTokenResponseConverter()` with a custom `Converter, OAuth2AccessTokenResponse>` that is used for converting the OAuth 2.0 Access Token Response parameters to an `OAuth2AccessTokenResponse`. +You can customize the conversion of Token Response parameters to an `OAuth2AccessTokenResponse` by calling `setAccessTokenResponseConverter()`. +The default implementation is `DefaultMapOAuth2AccessTokenResponseConverter`. `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`. +You can customize the conversion of Token Response parameters to an `OAuth2Error` by calling `setErrorConverter()`. [TIP] ==== @@ -307,6 +315,8 @@ Spring MVC `FormHttpMessageConverter` is required, as it is used when sending th ==== [#oauth2-client-{section-id}-access-token-response-parameters] +=== Customizing 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 @@ -318,7 +328,7 @@ Java:: ---- OAuth2AccessTokenResponseHttpMessageConverter accessTokenResponseMessageConverter = new OAuth2AccessTokenResponseHttpMessageConverter(); -accessTokenResponseMessageConverter.setAccessTokenResponseConverter((parameters) -> { +accessTokenResponseMessageConverter.setAccessTokenResponseConverter(parameters -> { // ... return OAuth2AccessTokenResponse.withToken("custom-token") // ... @@ -341,6 +351,8 @@ accessTokenResponseMessageConverter.setAccessTokenResponseConverter { parameters ====== [#oauth2-client-{section-id}-access-token-response-errors] +=== Customizing Error Handling + The following example provides a starting point for customizing the conversion of Error parameters to an `OAuth2Error`: .Customize Access Token Error Handler @@ -352,7 +364,7 @@ Java:: ---- OAuth2ErrorHttpMessageConverter errorConverter = new OAuth2ErrorHttpMessageConverter(); -errorConverter.setErrorConverter((parameters) -> { +errorConverter.setErrorConverter(parameters -> { // ... return new OAuth2Error("custom-error", "custom description", "custom-uri"); });