oauth2-client.adoc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. [[oauth2client]]
  2. == OAuth 2.0 Client
  3. 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].
  4. At a high-level, the core features available are:
  5. .Authorization Grant support
  6. * https://tools.ietf.org/html/rfc6749#section-1.3.1[Authorization Code]
  7. * https://tools.ietf.org/html/rfc6749#section-6[Refresh Token]
  8. * https://tools.ietf.org/html/rfc6749#section-1.3.4[Client Credentials]
  9. * https://tools.ietf.org/html/rfc6749#section-1.3.3[Resource Owner Password Credentials]
  10. .HTTP Client support
  11. * <<servlet-webclient, `WebClient` integration for Servlet Environments>> (for requesting protected resources)
  12. The `HttpSecurity.oauth2Client()` DSL provides a number of configuration options for customizing the core components used by OAuth 2.0 Client.
  13. In addition, `HttpSecurity.oauth2Client().authorizationCodeGrant()` enables the customization of the Authorization Code grant.
  14. The following code shows the complete configuration options provided by the `HttpSecurity.oauth2Client()` DSL:
  15. [source,java]
  16. ----
  17. @EnableWebSecurity
  18. public class OAuth2ClientSecurityConfig extends WebSecurityConfigurerAdapter {
  19. @Override
  20. protected void configure(HttpSecurity http) throws Exception {
  21. http
  22. .oauth2Client(oauth2Client ->
  23. oauth2Client
  24. .clientRegistrationRepository(this.clientRegistrationRepository())
  25. .authorizedClientRepository(this.authorizedClientRepository())
  26. .authorizedClientService(this.authorizedClientService())
  27. .authorizationCodeGrant(authorizationCodeGrant ->
  28. authorizationCodeGrant
  29. .authorizationRequestRepository(this.authorizationRequestRepository())
  30. .authorizationRequestResolver(this.authorizationRequestResolver())
  31. .accessTokenResponseClient(this.accessTokenResponseClient())
  32. )
  33. );
  34. }
  35. }
  36. ----
  37. The `OAuth2AuthorizedClientManager` is responsible for managing the authorization (or re-authorization) of an OAuth 2.0 Client, in collaboration with one or more `OAuth2AuthorizedClientProvider`(s).
  38. The following code shows an example of how to register an `OAuth2AuthorizedClientManager` `@Bean` and associate it with an `OAuth2AuthorizedClientProvider` composite that provides support for the `authorization_code`, `refresh_token`, `client_credentials` and `password` authorization grant types:
  39. [source,java]
  40. ----
  41. @Bean
  42. public OAuth2AuthorizedClientManager authorizedClientManager(
  43. ClientRegistrationRepository clientRegistrationRepository,
  44. OAuth2AuthorizedClientRepository authorizedClientRepository) {
  45. OAuth2AuthorizedClientProvider authorizedClientProvider =
  46. OAuth2AuthorizedClientProviderBuilder.builder()
  47. .authorizationCode()
  48. .refreshToken()
  49. .clientCredentials()
  50. .password()
  51. .build();
  52. DefaultOAuth2AuthorizedClientManager authorizedClientManager =
  53. new DefaultOAuth2AuthorizedClientManager(
  54. clientRegistrationRepository, authorizedClientRepository);
  55. authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
  56. return authorizedClientManager;
  57. }
  58. ----
  59. The following sections will go into more detail on the core components used by OAuth 2.0 Client and the configuration options available:
  60. * <<oauth2Client-core-interface-class>>
  61. ** <<oauth2Client-client-registration, ClientRegistration>>
  62. ** <<oauth2Client-client-registration-repo, ClientRegistrationRepository>>
  63. ** <<oauth2Client-authorized-client, OAuth2AuthorizedClient>>
  64. ** <<oauth2Client-authorized-repo-service, OAuth2AuthorizedClientRepository / OAuth2AuthorizedClientService>>
  65. ** <<oauth2Client-authorized-manager-provider, OAuth2AuthorizedClientManager / OAuth2AuthorizedClientProvider>>
  66. * <<oauth2Client-auth-grant-support>>
  67. ** <<oauth2Client-auth-code-grant, Authorization Code>>
  68. * <<oauth2Client-additional-features>>
  69. ** <<oauth2Client-registered-authorized-client, Resolving an Authorized Client>>
  70. [[oauth2Client-core-interface-class]]
  71. === Core Interfaces / Classes
  72. [[oauth2Client-client-registration]]
  73. ==== ClientRegistration
  74. `ClientRegistration` is a representation of a client registered with an OAuth 2.0 or OpenID Connect 1.0 Provider.
  75. A client registration holds information, such as client id, client secret, authorization grant type, redirect URI, scope(s), authorization URI, token URI, and other details.
  76. `ClientRegistration` and its properties are defined as follows:
  77. [source,java]
  78. ----
  79. public final class ClientRegistration {
  80. private String registrationId; <1>
  81. private String clientId; <2>
  82. private String clientSecret; <3>
  83. private ClientAuthenticationMethod clientAuthenticationMethod; <4>
  84. private AuthorizationGrantType authorizationGrantType; <5>
  85. private String redirectUriTemplate; <6>
  86. private Set<String> scopes; <7>
  87. private ProviderDetails providerDetails;
  88. private String clientName; <8>
  89. public class ProviderDetails {
  90. private String authorizationUri; <9>
  91. private String tokenUri; <10>
  92. private UserInfoEndpoint userInfoEndpoint;
  93. private String jwkSetUri; <11>
  94. private Map<String, Object> configurationMetadata; <12>
  95. public class UserInfoEndpoint {
  96. private String uri; <13>
  97. private AuthenticationMethod authenticationMethod; <14>
  98. private String userNameAttributeName; <15>
  99. }
  100. }
  101. }
  102. ----
  103. <1> `registrationId`: The ID that uniquely identifies the `ClientRegistration`.
  104. <2> `clientId`: The client identifier.
  105. <3> `clientSecret`: The client secret.
  106. <4> `clientAuthenticationMethod`: The method used to authenticate the Client with the Provider.
  107. The supported values are *basic*, *post* and *none* https://tools.ietf.org/html/rfc6749#section-2.1[(public clients)].
  108. <5> `authorizationGrantType`: The OAuth 2.0 Authorization Framework defines four https://tools.ietf.org/html/rfc6749#section-1.3[Authorization Grant] types.
  109. The supported values are `authorization_code`, `client_credentials`, `password` and `implicit`.
  110. <6> `redirectUriTemplate`: The client's registered redirect URI that the _Authorization Server_ redirects the end-user's user-agent
  111. to after the end-user has authenticated and authorized access to the client.
  112. <7> `scopes`: The scope(s) requested by the client during the Authorization Request flow, such as openid, email, or profile.
  113. <8> `clientName`: A descriptive name used for the client.
  114. The name may be used in certain scenarios, such as when displaying the name of the client in the auto-generated login page.
  115. <9> `authorizationUri`: The Authorization Endpoint URI for the Authorization Server.
  116. <10> `tokenUri`: The Token Endpoint URI for the Authorization Server.
  117. <11> `jwkSetUri`: The URI used to retrieve the https://tools.ietf.org/html/rfc7517[JSON Web Key (JWK)] Set from the Authorization Server,
  118. which contains the cryptographic key(s) used to verify the https://tools.ietf.org/html/rfc7515[JSON Web Signature (JWS)] of the ID Token and optionally the UserInfo Response.
  119. <12> `configurationMetadata`: The https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig[OpenID Provider Configuration Information].
  120. This information will only be available if the Spring Boot 2.x property `spring.security.oauth2.client.provider.[providerId].issuerUri` is configured.
  121. <13> `(userInfoEndpoint)uri`: The UserInfo Endpoint URI used to access the claims/attributes of the authenticated end-user.
  122. <14> `(userInfoEndpoint)authenticationMethod`: The authentication method used when sending the access token to the UserInfo Endpoint.
  123. The supported values are *header*, *form* and *query*.
  124. <15> `userNameAttributeName`: The name of the attribute returned in the UserInfo Response that references the Name or Identifier of the end-user.
  125. [[oauth2Client-client-registration-repo]]
  126. ==== ClientRegistrationRepository
  127. The `ClientRegistrationRepository` serves as a repository for OAuth 2.0 / OpenID Connect 1.0 `ClientRegistration`(s).
  128. [NOTE]
  129. Client registration information is ultimately stored and owned by the associated Authorization Server.
  130. This repository provides the ability to retrieve a sub-set of the primary client registration information, which is stored with the Authorization Server.
  131. Spring Boot 2.x 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 `ClientRegistrationRepository`.
  132. [NOTE]
  133. The default implementation of `ClientRegistrationRepository` is `InMemoryClientRegistrationRepository`.
  134. The auto-configuration also registers the `ClientRegistrationRepository` as a `@Bean` in the `ApplicationContext` so that it is available for dependency-injection, if needed by the application.
  135. The following listing shows an example:
  136. [source,java]
  137. ----
  138. @Controller
  139. public class OAuth2ClientController {
  140. @Autowired
  141. private ClientRegistrationRepository clientRegistrationRepository;
  142. @RequestMapping("/")
  143. public String index() {
  144. ClientRegistration oktaRegistration =
  145. this.clientRegistrationRepository.findByRegistrationId("okta");
  146. ...
  147. return "index";
  148. }
  149. }
  150. ----
  151. [[oauth2Client-authorized-client]]
  152. ==== OAuth2AuthorizedClient
  153. `OAuth2AuthorizedClient` is a representation of an Authorized Client.
  154. A client is considered to be authorized when the end-user (Resource Owner) has granted authorization to the client to access its protected resources.
  155. `OAuth2AuthorizedClient` serves the purpose of associating an `OAuth2AccessToken` (and optional `OAuth2RefreshToken`) to a `ClientRegistration` (client) and resource owner, who is the `Principal` end-user that granted the authorization.
  156. [[oauth2Client-authorized-repo-service]]
  157. ==== OAuth2AuthorizedClientRepository / OAuth2AuthorizedClientService
  158. `OAuth2AuthorizedClientRepository` is responsible for persisting `OAuth2AuthorizedClient`(s) between web requests.
  159. Whereas, the primary role of `OAuth2AuthorizedClientService` is to manage `OAuth2AuthorizedClient`(s) at the application-level.
  160. From a developer perspective, the `OAuth2AuthorizedClientRepository` or `OAuth2AuthorizedClientService` provides the capability to lookup an `OAuth2AccessToken` associated with a client so that it may be used to initiate a protected resource request.
  161. The following listing shows an example:
  162. [source,java]
  163. ----
  164. @Controller
  165. public class OAuth2ClientController {
  166. @Autowired
  167. private OAuth2AuthorizedClientService authorizedClientService;
  168. @RequestMapping("/")
  169. public String index(Authentication authentication) {
  170. OAuth2AuthorizedClient authorizedClient =
  171. this.authorizedClientService.loadAuthorizedClient("okta", authentication.getName());
  172. OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
  173. ...
  174. return "index";
  175. }
  176. }
  177. ----
  178. [NOTE]
  179. Spring Boot 2.x auto-configuration registers an `OAuth2AuthorizedClientRepository` and/or `OAuth2AuthorizedClientService` `@Bean` in the `ApplicationContext`.
  180. However, the application may choose to override and register a custom `OAuth2AuthorizedClientRepository` or `OAuth2AuthorizedClientService` `@Bean`.
  181. [[oauth2Client-authorized-manager-provider]]
  182. ==== OAuth2AuthorizedClientManager / OAuth2AuthorizedClientProvider
  183. The `OAuth2AuthorizedClientManager` is responsible for the overall management of `OAuth2AuthorizedClient`(s).
  184. The primary responsibilities include:
  185. * Authorizing (or re-authorizing) an OAuth 2.0 Client, using an `OAuth2AuthorizedClientProvider`.
  186. * Delegating the persistence of an `OAuth2AuthorizedClient`, typically using an `OAuth2AuthorizedClientService` or `OAuth2AuthorizedClientRepository`.
  187. An `OAuth2AuthorizedClientProvider` implements a strategy for authorizing (or re-authorizing) an OAuth 2.0 Client.
  188. Implementations will typically implement an authorization grant type, eg. `authorization_code`, `client_credentials`, etc.
  189. The default implementation of `OAuth2AuthorizedClientManager` is `DefaultOAuth2AuthorizedClientManager`, which is associated with an `OAuth2AuthorizedClientProvider` that may support multiple authorization grant types using a delegation-based composite.
  190. The `OAuth2AuthorizedClientProviderBuilder` may be used to configure and build the delegation-based composite.
  191. The following code shows an example of how to configure and build an `OAuth2AuthorizedClientProvider` composite that provides support for the `authorization_code`, `refresh_token`, `client_credentials` and `password` authorization grant types:
  192. [source,java]
  193. ----
  194. @Bean
  195. public OAuth2AuthorizedClientManager authorizedClientManager(
  196. ClientRegistrationRepository clientRegistrationRepository,
  197. OAuth2AuthorizedClientRepository authorizedClientRepository) {
  198. OAuth2AuthorizedClientProvider authorizedClientProvider =
  199. OAuth2AuthorizedClientProviderBuilder.builder()
  200. .authorizationCode()
  201. .refreshToken()
  202. .clientCredentials()
  203. .password()
  204. .build();
  205. DefaultOAuth2AuthorizedClientManager authorizedClientManager =
  206. new DefaultOAuth2AuthorizedClientManager(
  207. clientRegistrationRepository, authorizedClientRepository);
  208. authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
  209. return authorizedClientManager;
  210. }
  211. ----
  212. [NOTE]
  213. Spring Boot 2.x auto-configuration registers an `OAuth2AuthorizedClientManager` `@Bean` in the `ApplicationContext`.
  214. However, the application may choose to override and register a custom `OAuth2AuthorizedClientManager` `@Bean`.
  215. [[oauth2Client-auth-grant-support]]
  216. === Authorization Grant Support
  217. [[oauth2Client-auth-code-grant]]
  218. ==== Authorization Code
  219. [NOTE]
  220. 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.
  221. ===== Obtaining Authorization
  222. [NOTE]
  223. Please refer to the https://tools.ietf.org/html/rfc6749#section-4.1.1[Authorization Request/Response] protocol flow for the Authorization Code grant.
  224. ===== Initiating the Authorization Request
  225. 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.
  226. The primary role of the `OAuth2AuthorizationRequestResolver` is to resolve an `OAuth2AuthorizationRequest` from the provided web request.
  227. The default implementation `DefaultOAuth2AuthorizationRequestResolver` matches on the (default) path `/oauth2/authorization/{registrationId}` extracting the `registrationId` and using it to build the `OAuth2AuthorizationRequest` for the associated `ClientRegistration`.
  228. Given the following Spring Boot 2.x properties for an OAuth 2.0 Client registration:
  229. [source,yaml]
  230. ----
  231. spring:
  232. security:
  233. oauth2:
  234. client:
  235. registration:
  236. okta:
  237. client-id: okta-client-id
  238. client-secret: okta-client-secret
  239. authorization-grant-type: authorization_code
  240. redirect-uri: "{baseUrl}/authorized/okta"
  241. scope: read, write
  242. ----
  243. A request with the base path `/oauth2/authorization/okta` will initiate the Authorization Request redirect by the `OAuth2AuthorizationRequestRedirectFilter` and ultimately start the Authorization Code grant flow.
  244. [NOTE]
  245. The `AuthorizationCodeOAuth2AuthorizedClientProvider` is an implementation of `OAuth2AuthorizedClientProvider` for the Authorization Code grant,
  246. which also initiates the Authorization Request redirect by the `OAuth2AuthorizationRequestRedirectFilter`.
  247. ===== Customizing the Authorization Request
  248. 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.
  249. For example, OpenID Connect defines additional OAuth 2.0 request parameters for the https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest[Authorization Code Flow] extending from the standard parameters defined in the https://tools.ietf.org/html/rfc6749#section-4.1.1[OAuth 2.0 Authorization Framework].
  250. One of those extended parameters is the `prompt` parameter.
  251. [NOTE]
  252. OPTIONAL. Space delimited, case sensitive list of ASCII string values that specifies whether the Authorization Server prompts the End-User for reauthentication and consent. The defined values are: none, login, consent, select_account
  253. The following example shows how to implement an `OAuth2AuthorizationRequestResolver` that customizes the Authorization Request for `oauth2Login()`, by including the request parameter `prompt=consent`.
  254. [source,java]
  255. ----
  256. @EnableWebSecurity
  257. public class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
  258. @Autowired
  259. private ClientRegistrationRepository clientRegistrationRepository;
  260. @Override
  261. protected void configure(HttpSecurity http) throws Exception {
  262. http
  263. .authorizeRequests(authorizeRequests ->
  264. authorizeRequests
  265. .anyRequest().authenticated()
  266. )
  267. .oauth2Login(oauth2Login ->
  268. oauth2Login
  269. .authorizationEndpoint(authorizationEndpoint ->
  270. authorizationEndpoint
  271. .authorizationRequestResolver(
  272. new CustomAuthorizationRequestResolver(
  273. this.clientRegistrationRepository)) <1>
  274. )
  275. );
  276. }
  277. }
  278. public class CustomAuthorizationRequestResolver implements OAuth2AuthorizationRequestResolver {
  279. private final OAuth2AuthorizationRequestResolver defaultAuthorizationRequestResolver;
  280. public CustomAuthorizationRequestResolver(
  281. ClientRegistrationRepository clientRegistrationRepository) {
  282. this.defaultAuthorizationRequestResolver =
  283. new DefaultOAuth2AuthorizationRequestResolver(
  284. clientRegistrationRepository, "/oauth2/authorization");
  285. }
  286. @Override
  287. public OAuth2AuthorizationRequest resolve(HttpServletRequest request) {
  288. OAuth2AuthorizationRequest authorizationRequest =
  289. this.defaultAuthorizationRequestResolver.resolve(request); <2>
  290. return authorizationRequest != null ? <3>
  291. customAuthorizationRequest(authorizationRequest) :
  292. null;
  293. }
  294. @Override
  295. public OAuth2AuthorizationRequest resolve(
  296. HttpServletRequest request, String clientRegistrationId) {
  297. OAuth2AuthorizationRequest authorizationRequest =
  298. this.defaultAuthorizationRequestResolver.resolve(
  299. request, clientRegistrationId); <2>
  300. return authorizationRequest != null ? <3>
  301. customAuthorizationRequest(authorizationRequest) :
  302. null;
  303. }
  304. private OAuth2AuthorizationRequest customAuthorizationRequest(
  305. OAuth2AuthorizationRequest authorizationRequest) {
  306. Map<String, Object> additionalParameters =
  307. new LinkedHashMap<>(authorizationRequest.getAdditionalParameters());
  308. additionalParameters.put("prompt", "consent"); <4>
  309. return OAuth2AuthorizationRequest.from(authorizationRequest) <5>
  310. .additionalParameters(additionalParameters) <6>
  311. .build();
  312. }
  313. }
  314. ----
  315. <1> Configure the custom `OAuth2AuthorizationRequestResolver`
  316. <2> Attempt to resolve the `OAuth2AuthorizationRequest` using the `DefaultOAuth2AuthorizationRequestResolver`
  317. <3> If an `OAuth2AuthorizationRequest` was resolved than return a customized version else return `null`
  318. <4> Add custom parameters to the existing `OAuth2AuthorizationRequest.additionalParameters`
  319. <5> Create a copy of the default `OAuth2AuthorizationRequest` which returns an `OAuth2AuthorizationRequest.Builder` for further modifications
  320. <6> Override the default `additionalParameters`
  321. [TIP]
  322. `OAuth2AuthorizationRequest.Builder.build()` constructs the `OAuth2AuthorizationRequest.authorizationRequestUri`, which represents the complete Authorization Request URI including all query parameters using the `application/x-www-form-urlencoded` format.
  323. The preceding example shows the common use case of adding a custom parameter on top of the standard parameters.
  324. Alternatively, if your requirements are more advanced, than you can take full control in building the Authorization Request URI by simply overriding the `OAuth2AuthorizationRequest.authorizationRequestUri` property.
  325. The following example shows a variation of the `customAuthorizationRequest()` method from the preceding example, and instead overrides the `OAuth2AuthorizationRequest.authorizationRequestUri` property.
  326. [source,java]
  327. ----
  328. private OAuth2AuthorizationRequest customAuthorizationRequest(
  329. OAuth2AuthorizationRequest authorizationRequest) {
  330. String customAuthorizationRequestUri = UriComponentsBuilder
  331. .fromUriString(authorizationRequest.getAuthorizationRequestUri())
  332. .queryParam("prompt", "consent")
  333. .build(true)
  334. .toUriString();
  335. return OAuth2AuthorizationRequest.from(authorizationRequest)
  336. .authorizationRequestUri(customAuthorizationRequestUri)
  337. .build();
  338. }
  339. ----
  340. ===== Storing the Authorization Request
  341. 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).
  342. [TIP]
  343. The `OAuth2AuthorizationRequest` is used to correlate and validate the Authorization Response.
  344. The default implementation of `AuthorizationRequestRepository` is `HttpSessionOAuth2AuthorizationRequestRepository`, which stores the `OAuth2AuthorizationRequest` in the `HttpSession`.
  345. If you have a custom implementation of `AuthorizationRequestRepository`, you may configure it as shown in the following example:
  346. [source,java]
  347. ----
  348. @EnableWebSecurity
  349. public class OAuth2ClientSecurityConfig extends WebSecurityConfigurerAdapter {
  350. @Override
  351. protected void configure(HttpSecurity http) throws Exception {
  352. http
  353. .oauth2Client(oauth2Client ->
  354. oauth2Client
  355. .authorizationCodeGrant(authorizationCodeGrant ->
  356. authorizationCodeGrant
  357. .authorizationRequestRepository(this.customAuthorizationRequestRepository())
  358. ...
  359. )
  360. );
  361. }
  362. }
  363. ----
  364. ===== Requesting an Access Token
  365. [NOTE]
  366. Please refer to the https://tools.ietf.org/html/rfc6749#section-4.1.3[Access Token Request/Response] protocol flow for the Authorization Code grant.
  367. The primary role of the `OAuth2AccessTokenResponseClient` is to exchange an authorization grant credential for an access token credential at the Authorization Server's Token Endpoint.
  368. The default implementation of `OAuth2AccessTokenResponseClient` for the Authorization Code grant is `DefaultAuthorizationCodeTokenResponseClient`, which uses a `RestOperations` for exchanging an authorization code for an access token at the Token Endpoint.
  369. The `DefaultAuthorizationCodeTokenResponseClient` is quite flexible as it allows you to customize the pre-processing of the Token Request and/or post-handling of the Token Response.
  370. ===== Customizing the Access Token Request
  371. If you need to customize the pre-processing of the Token Request, you can provide `DefaultAuthorizationCodeTokenResponseClient.setRequestEntityConverter()` with a custom `Converter<OAuth2AuthorizationCodeGrantRequest, RequestEntity<?>>`.
  372. 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].
  373. However, providing a custom `Converter`, would allow you to extend the standard Token Request and add custom parameter(s).
  374. 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.
  375. ===== Customizing the Access Token Response
  376. On the other end, if you need to customize the post-handling of the Token Response, you will need to provide `DefaultAuthorizationCodeTokenResponseClient.setRestOperations()` with a custom configured `RestOperations`.
  377. The default `RestOperations` is configured as follows:
  378. [source,java]
  379. ----
  380. RestTemplate restTemplate = new RestTemplate(Arrays.asList(
  381. new FormHttpMessageConverter(),
  382. new OAuth2AccessTokenResponseHttpMessageConverter()));
  383. restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
  384. ----
  385. TIP: Spring MVC `FormHttpMessageConverter` is required as it's used when sending the OAuth 2.0 Access Token Request.
  386. `OAuth2AccessTokenResponseHttpMessageConverter` is a `HttpMessageConverter` for an OAuth 2.0 Access Token Response.
  387. You can provide `OAuth2AccessTokenResponseHttpMessageConverter.setTokenResponseConverter()` with a custom `Converter<Map<String, String>, OAuth2AccessTokenResponse>` that is used for converting the OAuth 2.0 Access Token Response parameters to an `OAuth2AccessTokenResponse`.
  388. `OAuth2ErrorResponseErrorHandler` is a `ResponseErrorHandler` that can handle an OAuth 2.0 Error, eg. 400 Bad Request.
  389. It uses an `OAuth2ErrorHttpMessageConverter` for converting the OAuth 2.0 Error parameters to an `OAuth2Error`.
  390. Whether you customize `DefaultAuthorizationCodeTokenResponseClient` or provide your own implementation of `OAuth2AccessTokenResponseClient`, you'll need to configure it as shown in the following example:
  391. [source,java]
  392. ----
  393. @EnableWebSecurity
  394. public class OAuth2ClientSecurityConfig extends WebSecurityConfigurerAdapter {
  395. @Override
  396. protected void configure(HttpSecurity http) throws Exception {
  397. http
  398. .oauth2Client(oauth2Client ->
  399. oauth2Client
  400. .authorizationCodeGrant(authorizationCodeGrant ->
  401. authorizationCodeGrant
  402. .accessTokenResponseClient(this.customAccessTokenResponseClient())
  403. ...
  404. )
  405. );
  406. }
  407. }
  408. ----
  409. [[oauth2Client-additional-features]]
  410. === Additional Features
  411. [[oauth2Client-registered-authorized-client]]
  412. ==== Resolving an Authorized Client
  413. The `@RegisteredOAuth2AuthorizedClient` annotation provides the capability of resolving a method parameter to an argument value of type `OAuth2AuthorizedClient`.
  414. This is a convenient alternative compared to looking up the `OAuth2AuthorizedClient` via the `OAuth2AuthorizedClientService`.
  415. [source,java]
  416. ----
  417. @Controller
  418. public class OAuth2ClientController {
  419. @RequestMapping("/")
  420. public String index(@RegisteredOAuth2AuthorizedClient("okta") OAuth2AuthorizedClient authorizedClient) {
  421. OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
  422. ...
  423. return "index";
  424. }
  425. }
  426. ----
  427. The `@RegisteredOAuth2AuthorizedClient` annotation is handled by `OAuth2AuthorizedClientArgumentResolver` and provides the following capabilities:
  428. * An `OAuth2AccessToken` will be requested if the client has not yet been authorized.
  429. ** `authorization_code` - triggers the authorization request redirect to initiate the flow
  430. ** `client_credentials` - the access token is obtained directly from the Token Endpoint
  431. ** `password` - the access token is obtained directly from the Token Endpoint
  432. * If the `OAuth2AccessToken` is expired, it will be renewed (or refreshed) if an `OAuth2AuthorizedClientProvider` is available to perform the authorization