diff --git a/docs/manual/src/docs/asciidoc/_includes/servlet/preface/oauth2-client.adoc b/docs/manual/src/docs/asciidoc/_includes/servlet/preface/oauth2-client.adoc index 6ce8f8f60e..3f2b424b36 100644 --- a/docs/manual/src/docs/asciidoc/_includes/servlet/preface/oauth2-client.adoc +++ b/docs/manual/src/docs/asciidoc/_includes/servlet/preface/oauth2-client.adoc @@ -81,6 +81,7 @@ The following sections will go into more detail on the core components used by O ** <> * <> ** <> +** <> * <> ** <> @@ -551,6 +552,160 @@ public class OAuth2ClientSecurityConfig extends WebSecurityConfigurerAdapter { ---- +[[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. + + +===== Requesting an Access Token + +[NOTE] +Please refer to the https://tools.ietf.org/html/rfc6749#section-4.4.2[Access Token Request/Response] protocol flow for the 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. + +The `DefaultClientCredentialsTokenResponseClient` is quite flexible as it allows you to customize the pre-processing of the Token Request and/or post-handling of the Token Response. + + +===== 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>`. +The default implementation `OAuth2ClientCredentialsRequestEntityConverter` 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 allow you to extend the standard Token Request and add custom parameter(s). + +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. + + +===== 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 `DefaultClientCredentialsTokenResponseClient.setRestOperations()` with a custom configured `RestOperations`. +The default `RestOperations` is configured as follows: + +[source,java] +---- +RestTemplate restTemplate = new RestTemplate(Arrays.asList( + new FormHttpMessageConverter(), + new OAuth2AccessTokenResponseHttpMessageConverter())); + +restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler()); +---- + +TIP: Spring MVC `FormHttpMessageConverter` is required as it's 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.setTokenResponseConverter()` with a custom `Converter, 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, eg. 400 Bad Request. +It uses an `OAuth2ErrorHttpMessageConverter` for converting the OAuth 2.0 Error parameters to an `OAuth2Error`. + +Whether you customize `DefaultClientCredentialsTokenResponseClient` or provide your own implementation of `OAuth2AccessTokenResponseClient`, you'll need to configure it as shown in the following example: + +[source,java] +---- +// Customize +OAuth2AccessTokenResponseClient clientCredentialsTokenResponseClient = ... + +OAuth2AuthorizedClientProvider authorizedClientProvider = + OAuth2AuthorizedClientProviderBuilder.builder() + .clientCredentials(configurer -> configurer.accessTokenResponseClient(clientCredentialsTokenResponseClient)) + .build(); + +... + +authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); +---- + +[NOTE] +`OAuth2AuthorizedClientProviderBuilder.builder().clientCredentials()` configures a `ClientCredentialsOAuth2AuthorizedClientProvider`, +which is an implementation of an `OAuth2AuthorizedClientProvider` for the Client Credentials grant. + +===== Using the Access Token + +Given the following Spring Boot 2.x properties for an OAuth 2.0 Client registration: + +[source,yaml] +---- +spring: + security: + oauth2: + client: + registration: + okta: + client-id: okta-client-id + client-secret: okta-client-secret + authorization-grant-type: client_credentials + scope: read, write + provider: + okta: + token-uri: https://dev-1234.oktapreview.com/oauth2/v1/token +---- + +...and the `OAuth2AuthorizedClientManager` `@Bean`: + +[source,java] +---- +@Bean +public OAuth2AuthorizedClientManager authorizedClientManager( + ClientRegistrationRepository clientRegistrationRepository, + OAuth2AuthorizedClientRepository authorizedClientRepository) { + + OAuth2AuthorizedClientProvider authorizedClientProvider = + OAuth2AuthorizedClientProviderBuilder.builder() + .clientCredentials() + .build(); + + DefaultOAuth2AuthorizedClientManager authorizedClientManager = + new DefaultOAuth2AuthorizedClientManager( + clientRegistrationRepository, authorizedClientRepository); + authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); + + return authorizedClientManager; +} +---- + +[NOTE] +Spring Boot 2.x auto-configuration registers an `OAuth2AuthorizedClientManager` `@Bean` in the `ApplicationContext`. + +You may obtain the `OAuth2AccessToken` as follows: + +[source,java] +---- +@Controller +public class OAuth2ClientController { + + @Autowired + private OAuth2AuthorizedClientManager authorizedClientManager; + + @GetMapping("/") + public String index(Authentication authentication, + HttpServletRequest servletRequest, + HttpServletResponse servletResponse) { + + OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("okta") + .principal(authentication) + .attributes(attrs -> { + attrs.put(HttpServletRequest.class.getName(), servletRequest); + attrs.put(HttpServletResponse.class.getName(), servletResponse); + }) + .build(); + OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest); + + OAuth2AccessToken accessToken = authorizedClient.getAccessToken(); + + ... + + return "index"; + } +} +---- + +[NOTE] +`HttpServletRequest` and `HttpServletResponse` are both OPTIONAL attributes. +If not provided, it will default to `ServletRequestAttributes` using `RequestContextHolder.getRequestAttributes()`. + + [[oauth2Client-additional-features]] === Additional Features