123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390 |
- 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 accessTokenResponseClient(): OAuth2AccessTokenResponseClient<{grant-type}> {
- return {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-rest-client,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 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:
- * 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, "my-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] = "my-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 three options for customizing request parameters:
- * 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 calling `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
- `{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 `RestClient`
- 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 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]
- ====
- 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]
- === 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
- [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]
- === 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
- [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)
- ----
- ======
|