2
0

authorization-grants.adoc 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227
  1. [[oauth2-client-authorization-grants]]
  2. = [[oauth2Client-auth-grant-support]]Authorization Grant Support
  3. :spring-security-reference-base-url: https://docs.spring.io/spring-security/reference
  4. This section describes Spring Security's support for authorization grants.
  5. [[oauth2-client-authorization-code]]
  6. == [[oauth2Client-auth-code-grant]]Authorization Code
  7. [NOTE]
  8. ====
  9. 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.
  10. ====
  11. [[oauth2-client-authorization-code-authorization]]
  12. === Obtaining Authorization
  13. [NOTE]
  14. ====
  15. See the https://tools.ietf.org/html/rfc6749#section-4.1.1[Authorization Request/Response] protocol flow for the Authorization Code grant.
  16. ====
  17. [[oauth2-client-authorization-code-authorization-request]]
  18. === Initiating the Authorization Request
  19. 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.
  20. The primary role of the `OAuth2AuthorizationRequestResolver` is to resolve an `OAuth2AuthorizationRequest` from the provided web request.
  21. 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`.
  22. Consider the following Spring Boot properties for an OAuth 2.0 Client registration:
  23. [source,yaml,attrs="-attributes"]
  24. ----
  25. spring:
  26. security:
  27. oauth2:
  28. client:
  29. registration:
  30. okta:
  31. client-id: okta-client-id
  32. client-secret: okta-client-secret
  33. authorization-grant-type: authorization_code
  34. redirect-uri: "{baseUrl}/authorized/okta"
  35. scope: read, write
  36. provider:
  37. okta:
  38. authorization-uri: https://dev-1234.oktapreview.com/oauth2/v1/authorize
  39. token-uri: https://dev-1234.oktapreview.com/oauth2/v1/token
  40. ----
  41. Given the preceding properties, a request with the base path `/oauth2/authorization/okta` initiates the Authorization Request redirect by the `OAuth2AuthorizationRequestRedirectFilter` and ultimately starts the Authorization Code grant flow.
  42. [NOTE]
  43. ====
  44. The `AuthorizationCodeOAuth2AuthorizedClientProvider` is an implementation of `OAuth2AuthorizedClientProvider` for the Authorization Code grant,
  45. which also initiates the Authorization Request redirect by the `OAuth2AuthorizationRequestRedirectFilter`.
  46. ====
  47. If the OAuth 2.0 Client is a https://tools.ietf.org/html/rfc6749#section-2.1[Public Client], configure the OAuth 2.0 Client registration as follows:
  48. [source,yaml,attrs="-attributes"]
  49. ----
  50. spring:
  51. security:
  52. oauth2:
  53. client:
  54. registration:
  55. okta:
  56. client-id: okta-client-id
  57. client-authentication-method: none
  58. authorization-grant-type: authorization_code
  59. redirect-uri: "{baseUrl}/authorized/okta"
  60. # ...
  61. ----
  62. Public Clients are supported by using https://tools.ietf.org/html/rfc7636[Proof Key for Code Exchange] (PKCE).
  63. If the client is running in an untrusted environment (such as a native application or web browser-based application) and is therefore incapable of maintaining the confidentiality of its credentials, PKCE is automatically used when the following conditions are true:
  64. . `client-secret` is omitted (or empty) and
  65. . `client-authentication-method` is set to `none` (`ClientAuthenticationMethod.NONE`)
  66. or
  67. . When `ClientRegistration.clientSettings.requireProofKey` is `true` (in this case `ClientRegistration.authorizationGrantType` must be `authorization_code`)
  68. [TIP]
  69. ====
  70. 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())`.
  71. ====
  72. [[oauth2-client-authorization-code-redirect-uri]]
  73. [[oauth2Client-auth-code-redirect-uri]]The `DefaultOAuth2AuthorizationRequestResolver` also supports `URI` template variables for the `redirect-uri` by using `UriComponentsBuilder`.
  74. The following configuration uses all the supported `URI` template variables:
  75. [source,yaml,attrs="-attributes"]
  76. ----
  77. spring:
  78. security:
  79. oauth2:
  80. client:
  81. registration:
  82. okta:
  83. # ...
  84. redirect-uri: "{baseScheme}://{baseHost}{basePort}{basePath}/authorized/{registrationId}"
  85. # ...
  86. ----
  87. [NOTE]
  88. ====
  89. `+{baseUrl}+` resolves to `+{baseScheme}://{baseHost}{basePort}{basePath}+`
  90. ====
  91. 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].
  92. Doing so ensures that the `X-Forwarded-*` headers are used when expanding the `redirect-uri`.
  93. [[oauth2-client-authorization-code-authorization-request-resolver]]
  94. === Customizing the Authorization Request
  95. 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.
  96. 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].
  97. One of those extended parameters is the `prompt` parameter.
  98. [NOTE]
  99. ====
  100. The `prompt` parameter is optional. Space delimited, case sensitive list of ASCII string values that specifies whether the Authorization Server prompts the End-User for re-authentication and consent. The defined values are: `none`, `login`, `consent`, and `select_account`.
  101. ====
  102. The following example shows how to configure the `DefaultOAuth2AuthorizationRequestResolver` with a `Consumer<OAuth2AuthorizationRequest.Builder>` that customizes the Authorization Request for `oauth2Login()`, by including the request parameter `prompt=consent`.
  103. [tabs]
  104. ======
  105. Java::
  106. +
  107. [source,java,role="primary"]
  108. ----
  109. @Configuration
  110. @EnableWebSecurity
  111. public class OAuth2LoginSecurityConfig {
  112. @Autowired
  113. private ClientRegistrationRepository clientRegistrationRepository;
  114. @Bean
  115. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  116. http
  117. .authorizeHttpRequests((authorize) -> authorize
  118. .anyRequest().authenticated()
  119. )
  120. .oauth2Login((oauth2) -> oauth2
  121. .authorizationEndpoint((authorization) -> authorization
  122. .authorizationRequestResolver(
  123. authorizationRequestResolver(this.clientRegistrationRepository)
  124. )
  125. )
  126. );
  127. return http.build();
  128. }
  129. private OAuth2AuthorizationRequestResolver authorizationRequestResolver(
  130. ClientRegistrationRepository clientRegistrationRepository) {
  131. DefaultOAuth2AuthorizationRequestResolver authorizationRequestResolver =
  132. new DefaultOAuth2AuthorizationRequestResolver(
  133. clientRegistrationRepository, "/oauth2/authorization");
  134. authorizationRequestResolver.setAuthorizationRequestCustomizer(
  135. authorizationRequestCustomizer());
  136. return authorizationRequestResolver;
  137. }
  138. private Consumer<OAuth2AuthorizationRequest.Builder> authorizationRequestCustomizer() {
  139. return customizer -> customizer
  140. .additionalParameters((params) -> params.put("prompt", "consent"));
  141. }
  142. }
  143. ----
  144. Kotlin::
  145. +
  146. [source,kotlin,role="secondary"]
  147. ----
  148. @Configuration
  149. @EnableWebSecurity
  150. class SecurityConfig {
  151. @Autowired
  152. private lateinit var customClientRegistrationRepository: ClientRegistrationRepository
  153. @Bean
  154. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  155. http {
  156. authorizeRequests {
  157. authorize(anyRequest, authenticated)
  158. }
  159. oauth2Login {
  160. authorizationEndpoint {
  161. authorizationRequestResolver = authorizationRequestResolver(customClientRegistrationRepository)
  162. }
  163. }
  164. }
  165. return http.build()
  166. }
  167. private fun authorizationRequestResolver(
  168. clientRegistrationRepository: ClientRegistrationRepository?): OAuth2AuthorizationRequestResolver {
  169. val authorizationRequestResolver = DefaultOAuth2AuthorizationRequestResolver(
  170. clientRegistrationRepository, "/oauth2/authorization")
  171. authorizationRequestResolver.setAuthorizationRequestCustomizer(
  172. authorizationRequestCustomizer())
  173. return authorizationRequestResolver
  174. }
  175. private fun authorizationRequestCustomizer(): Consumer<OAuth2AuthorizationRequest.Builder> {
  176. return Consumer { customizer ->
  177. customizer
  178. .additionalParameters { params -> params["prompt"] = "consent" }
  179. }
  180. }
  181. }
  182. ----
  183. ======
  184. For the simple use case where the additional request parameter is always the same for a specific provider, you can add it directly in the `authorization-uri` property.
  185. For example, if the value for the request parameter `prompt` is always `consent` for the provider `okta`, you can configure it as follows:
  186. [source,yaml]
  187. ----
  188. spring:
  189. security:
  190. oauth2:
  191. client:
  192. provider:
  193. okta:
  194. authorization-uri: https://dev-1234.oktapreview.com/oauth2/v1/authorize?prompt=consent
  195. ----
  196. The preceding example shows the common use case of adding a custom parameter on top of the standard parameters.
  197. Alternatively, if your requirements are more advanced, you can take full control in building the Authorization Request URI by overriding the `OAuth2AuthorizationRequest.authorizationRequestUri` property.
  198. [TIP]
  199. ====
  200. `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.
  201. ====
  202. The following example shows a variation of `authorizationRequestCustomizer()` from the preceding example and instead overrides the `OAuth2AuthorizationRequest.authorizationRequestUri` property:
  203. [tabs]
  204. ======
  205. Java::
  206. +
  207. [source,java,role="primary"]
  208. ----
  209. private Consumer<OAuth2AuthorizationRequest.Builder> authorizationRequestCustomizer() {
  210. return customizer -> customizer
  211. .authorizationRequestUri((uriBuilder) -> uriBuilder
  212. .queryParam("prompt", "consent").build());
  213. }
  214. ----
  215. Kotlin::
  216. +
  217. [source,kotlin,role="secondary"]
  218. ----
  219. private fun authorizationRequestCustomizer(): Consumer<OAuth2AuthorizationRequest.Builder> {
  220. return Consumer { customizer: OAuth2AuthorizationRequest.Builder ->
  221. customizer
  222. .authorizationRequestUri { uriBuilder: UriBuilder ->
  223. uriBuilder
  224. .queryParam("prompt", "consent").build()
  225. }
  226. }
  227. }
  228. ----
  229. ======
  230. [[oauth2-client-authorization-code-authorization-request-repository]]
  231. === Storing the Authorization Request
  232. 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).
  233. [TIP]
  234. ====
  235. The `OAuth2AuthorizationRequest` is used to correlate and validate the Authorization Response.
  236. ====
  237. The default implementation of `AuthorizationRequestRepository` is `HttpSessionOAuth2AuthorizationRequestRepository`, which stores the `OAuth2AuthorizationRequest` in the `HttpSession`.
  238. If you have a custom implementation of `AuthorizationRequestRepository`, you can configure it as follows:
  239. .AuthorizationRequestRepository Configuration
  240. [tabs]
  241. ======
  242. Java::
  243. +
  244. [source,java,role="primary"]
  245. ----
  246. @Configuration
  247. @EnableWebSecurity
  248. public class OAuth2ClientSecurityConfig {
  249. @Bean
  250. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  251. http
  252. .oauth2Client((oauth2) -> oauth2
  253. .authorizationCodeGrant((codeGrant) -> codeGrant
  254. .authorizationRequestRepository(this.authorizationRequestRepository())
  255. // ...
  256. )
  257. )
  258. .oauth2Login((oauth2) -> oauth2
  259. .authorizationEndpoint((endpoint) -> endpoint
  260. .authorizationRequestRepository(this.authorizationRequestRepository())
  261. // ...
  262. )
  263. );
  264. return http.build();
  265. }
  266. @Bean
  267. public AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository() {
  268. return new CustomOAuth2AuthorizationRequestRepository();
  269. }
  270. }
  271. ----
  272. Kotlin::
  273. +
  274. [source,kotlin,role="secondary"]
  275. ----
  276. @Configuration
  277. @EnableWebSecurity
  278. class OAuth2ClientSecurityConfig {
  279. @Bean
  280. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  281. http {
  282. oauth2Client {
  283. authorizationCodeGrant {
  284. authorizationRequestRepository = authorizationRequestRepository()
  285. }
  286. }
  287. }
  288. return http.build()
  289. }
  290. }
  291. ----
  292. Xml::
  293. +
  294. [source,xml,role="secondary"]
  295. ----
  296. <http>
  297. <oauth2-client>
  298. <authorization-code-grant authorization-request-repository-ref="authorizationRequestRepository"/>
  299. </oauth2-client>
  300. </http>
  301. ----
  302. ======
  303. [[oauth2-client-authorization-code-access-token]]
  304. === Requesting an Access Token
  305. [NOTE]
  306. ====
  307. See the https://tools.ietf.org/html/rfc6749#section-4.1.3[Access Token Request/Response] protocol flow for the Authorization Code grant.
  308. ====
  309. 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:
  310. * `DefaultAuthorizationCodeTokenResponseClient` (_default_)
  311. * `RestClientAuthorizationCodeTokenResponseClient`
  312. The default implementation uses a `RestOperations` instance to exchange an authorization code for an access token at the Authorization Server’s Token Endpoint.
  313. 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.
  314. [NOTE]
  315. ====
  316. This section focuses on `RestClientAuthorizationCodeTokenResponseClient`.
  317. 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.
  318. ====
  319. :section-id: authorization-code
  320. :grant-type: Authorization Code
  321. :class-name: RestClientAuthorizationCodeTokenResponseClient
  322. :grant-request: OAuth2AuthorizationCodeGrantRequest
  323. :leveloffset: +1
  324. include::partial$servlet/oauth2/client/rest-client-access-token-response-client.adoc[]
  325. :leveloffset: -1
  326. [[oauth2-client-authorization-code-access-token-response-client-dsl]]
  327. === Customize using the DSL
  328. 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:
  329. .Access Token Response Configuration via DSL
  330. [tabs]
  331. ======
  332. Java::
  333. +
  334. [source,java,role="primary"]
  335. ----
  336. @Configuration
  337. @EnableWebSecurity
  338. public class OAuth2ClientSecurityConfig {
  339. @Bean
  340. public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  341. http
  342. .oauth2Client((oauth2) -> oauth2
  343. .authorizationCodeGrant((codeGrant) -> codeGrant
  344. .accessTokenResponseClient(this.accessTokenResponseClient())
  345. // ...
  346. )
  347. );
  348. return http.build();
  349. }
  350. }
  351. ----
  352. Kotlin::
  353. +
  354. [source,kotlin,role="secondary"]
  355. ----
  356. @Configuration
  357. @EnableWebSecurity
  358. class OAuth2ClientSecurityConfig {
  359. @Bean
  360. open fun filterChain(http: HttpSecurity): SecurityFilterChain {
  361. http {
  362. oauth2Client {
  363. authorizationCodeGrant {
  364. accessTokenResponseClient = accessTokenResponseClient()
  365. }
  366. }
  367. }
  368. return http.build()
  369. }
  370. }
  371. ----
  372. Xml::
  373. +
  374. [source,xml,role="secondary"]
  375. ----
  376. <http>
  377. <oauth2-client>
  378. <authorization-code-grant access-token-response-client-ref="accessTokenResponseClient"/>
  379. </oauth2-client>
  380. </http>
  381. ----
  382. ======
  383. [[oauth2-client-refresh-token]]
  384. == [[oauth2Client-refresh-token-grant]]Refresh Token
  385. [NOTE]
  386. ====
  387. See the OAuth 2.0 Authorization Framework for further details on the https://tools.ietf.org/html/rfc6749#section-1.5[Refresh Token].
  388. ====
  389. [[oauth2-client-refresh-token-access-token]]
  390. === Refreshing an Access Token
  391. [NOTE]
  392. ====
  393. See the https://tools.ietf.org/html/rfc6749#section-6[Access Token Request/Response] protocol flow for the Refresh Token grant.
  394. ====
  395. 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:
  396. * `DefaultRefreshTokenTokenResponseClient` (_default_)
  397. * `RestClientRefreshTokenTokenResponseClient`
  398. The default implementation uses a `RestOperations` instance to exchange an authorization code for an access token at the Authorization Server’s Token Endpoint.
  399. 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.
  400. [NOTE]
  401. ====
  402. This section focuses on `RestClientRefreshTokenTokenResponseClient`.
  403. 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.
  404. ====
  405. :section-id: refresh-token
  406. :grant-type: Refresh Token
  407. :class-name: RestClientRefreshTokenTokenResponseClient
  408. :grant-request: OAuth2RefreshTokenGrantRequest
  409. :leveloffset: +1
  410. include::partial$servlet/oauth2/client/rest-client-access-token-response-client.adoc[]
  411. :leveloffset: -1
  412. [[oauth2-client-refresh-token-authorized-client-provider-builder]]
  413. === Customize using the Builder
  414. 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:
  415. .Access Token Response Configuration via Builder
  416. [tabs]
  417. ======
  418. Java::
  419. +
  420. [source,java,role="primary"]
  421. ----
  422. // Customize
  423. OAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> refreshTokenTokenResponseClient = ...
  424. OAuth2AuthorizedClientProvider authorizedClientProvider =
  425. OAuth2AuthorizedClientProviderBuilder.builder()
  426. .authorizationCode()
  427. .refreshToken((configurer) -> configurer.accessTokenResponseClient(refreshTokenTokenResponseClient))
  428. .build();
  429. // ...
  430. authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
  431. ----
  432. Kotlin::
  433. +
  434. [source,kotlin,role="secondary"]
  435. ----
  436. // Customize
  437. val refreshTokenTokenResponseClient: OAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> = ...
  438. val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
  439. .authorizationCode()
  440. .refreshToken { it.accessTokenResponseClient(refreshTokenTokenResponseClient) }
  441. .build()
  442. // ...
  443. authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
  444. ----
  445. ======
  446. [NOTE]
  447. ====
  448. `OAuth2AuthorizedClientProviderBuilder.builder().refreshToken()` configures a `RefreshTokenOAuth2AuthorizedClientProvider`,
  449. which is an implementation of an `OAuth2AuthorizedClientProvider` for the Refresh Token grant.
  450. ====
  451. The `OAuth2RefreshToken` can optionally be returned in the Access Token Response for the `authorization_code` grant type.
  452. If the `OAuth2AuthorizedClient.getRefreshToken()` is available and the `OAuth2AuthorizedClient.getAccessToken()` is expired, it is automatically refreshed by the `RefreshTokenOAuth2AuthorizedClientProvider`.
  453. [[oauth2-client-client-credentials]]
  454. == [[oauth2Client-client-creds-grant]]Client Credentials
  455. [NOTE]
  456. ====
  457. 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.
  458. ====
  459. [[oauth2-client-client-credentials-access-token]]
  460. === Requesting an Access Token
  461. [NOTE]
  462. ====
  463. See the https://tools.ietf.org/html/rfc6749#section-4.4.2[Access Token Request/Response] protocol flow for the Client Credentials grant.
  464. ====
  465. 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:
  466. * `DefaultClientCredentialsTokenResponseClient` (_default_)
  467. * `RestClientClientCredentialsTokenResponseClient`
  468. The default implementation uses a `RestOperations` instance to exchange an authorization code for an access token at the Authorization Server’s Token Endpoint.
  469. 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.
  470. [NOTE]
  471. ====
  472. This section focuses on `RestClientClientCredentialsTokenResponseClient`.
  473. 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.
  474. ====
  475. :section-id: client-credentials
  476. :grant-type: Client Credentials
  477. :class-name: RestClientClientCredentialsTokenResponseClient
  478. :grant-request: OAuth2ClientCredentialsGrantRequest
  479. :leveloffset: +1
  480. include::partial$servlet/oauth2/client/rest-client-access-token-response-client.adoc[]
  481. :leveloffset: -1
  482. [[oauth2-client-client-credentials-authorized-client-provider-builder]]
  483. === Customize using the Builder
  484. 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:
  485. .Access Token Response Configuration via Builder
  486. [tabs]
  487. ======
  488. Java::
  489. +
  490. [source,java,role="primary"]
  491. ----
  492. // Customize
  493. OAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> clientCredentialsTokenResponseClient = ...
  494. OAuth2AuthorizedClientProvider authorizedClientProvider =
  495. OAuth2AuthorizedClientProviderBuilder.builder()
  496. .clientCredentials((configurer) -> configurer.accessTokenResponseClient(clientCredentialsTokenResponseClient))
  497. .build();
  498. // ...
  499. authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
  500. ----
  501. Kotlin::
  502. +
  503. [source,kotlin,role="secondary"]
  504. ----
  505. // Customize
  506. val clientCredentialsTokenResponseClient: OAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> = ...
  507. val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
  508. .clientCredentials { it.accessTokenResponseClient(clientCredentialsTokenResponseClient) }
  509. .build()
  510. // ...
  511. authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
  512. ----
  513. ======
  514. [NOTE]
  515. ====
  516. `OAuth2AuthorizedClientProviderBuilder.builder().clientCredentials()` configures a `ClientCredentialsOAuth2AuthorizedClientProvider`,
  517. which is an implementation of an `OAuth2AuthorizedClientProvider` for the Client Credentials grant.
  518. ====
  519. [[oauth2-client-client-credentials-authorized-client-manager]]
  520. === Using the Access Token
  521. Consider the following Spring Boot properties for an OAuth 2.0 Client registration:
  522. [source,yaml]
  523. ----
  524. spring:
  525. security:
  526. oauth2:
  527. client:
  528. registration:
  529. okta:
  530. client-id: okta-client-id
  531. client-secret: okta-client-secret
  532. authorization-grant-type: client_credentials
  533. scope: read, write
  534. provider:
  535. okta:
  536. token-uri: https://dev-1234.oktapreview.com/oauth2/v1/token
  537. ----
  538. Further consider the following `OAuth2AuthorizedClientManager` `@Bean`:
  539. [tabs]
  540. ======
  541. Java::
  542. +
  543. [source,java,role="primary"]
  544. ----
  545. @Bean
  546. public OAuth2AuthorizedClientManager authorizedClientManager(
  547. ClientRegistrationRepository clientRegistrationRepository,
  548. OAuth2AuthorizedClientRepository authorizedClientRepository) {
  549. OAuth2AuthorizedClientProvider authorizedClientProvider =
  550. OAuth2AuthorizedClientProviderBuilder.builder()
  551. .clientCredentials()
  552. .build();
  553. DefaultOAuth2AuthorizedClientManager authorizedClientManager =
  554. new DefaultOAuth2AuthorizedClientManager(
  555. clientRegistrationRepository, authorizedClientRepository);
  556. authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
  557. return authorizedClientManager;
  558. }
  559. ----
  560. Kotlin::
  561. +
  562. [source,kotlin,role="secondary"]
  563. ----
  564. @Bean
  565. fun authorizedClientManager(
  566. clientRegistrationRepository: ClientRegistrationRepository,
  567. authorizedClientRepository: OAuth2AuthorizedClientRepository): OAuth2AuthorizedClientManager {
  568. val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
  569. .clientCredentials()
  570. .build()
  571. val authorizedClientManager = DefaultOAuth2AuthorizedClientManager(
  572. clientRegistrationRepository, authorizedClientRepository)
  573. authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
  574. return authorizedClientManager
  575. }
  576. ----
  577. ======
  578. Given the preceding properties and bean, you can obtain the `OAuth2AccessToken` as follows:
  579. [tabs]
  580. ======
  581. Java::
  582. +
  583. [source,java,role="primary"]
  584. ----
  585. @Controller
  586. public class OAuth2ClientController {
  587. @Autowired
  588. private OAuth2AuthorizedClientManager authorizedClientManager;
  589. @GetMapping("/")
  590. public String index(Authentication authentication,
  591. HttpServletRequest servletRequest,
  592. HttpServletResponse servletResponse) {
  593. OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("okta")
  594. .principal(authentication)
  595. .attributes(attrs -> {
  596. attrs.put(HttpServletRequest.class.getName(), servletRequest);
  597. attrs.put(HttpServletResponse.class.getName(), servletResponse);
  598. })
  599. .build();
  600. OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest);
  601. OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
  602. // ...
  603. return "index";
  604. }
  605. }
  606. ----
  607. Kotlin::
  608. +
  609. [source,kotlin,role="secondary"]
  610. ----
  611. class OAuth2ClientController {
  612. @Autowired
  613. private lateinit var authorizedClientManager: OAuth2AuthorizedClientManager
  614. @GetMapping("/")
  615. fun index(authentication: Authentication?,
  616. servletRequest: HttpServletRequest,
  617. servletResponse: HttpServletResponse): String {
  618. val authorizeRequest: OAuth2AuthorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("okta")
  619. .principal(authentication)
  620. .attributes(Consumer { attrs: MutableMap<String, Any> ->
  621. attrs[HttpServletRequest::class.java.name] = servletRequest
  622. attrs[HttpServletResponse::class.java.name] = servletResponse
  623. })
  624. .build()
  625. val authorizedClient = authorizedClientManager.authorize(authorizeRequest)
  626. val accessToken: OAuth2AccessToken = authorizedClient.accessToken
  627. // ...
  628. return "index"
  629. }
  630. }
  631. ----
  632. ======
  633. [NOTE]
  634. ====
  635. `HttpServletRequest` and `HttpServletResponse` are both OPTIONAL attributes.
  636. If not provided, they default to `ServletRequestAttributes` by using `RequestContextHolder.getRequestAttributes()`.
  637. ====
  638. [[oauth2-client-jwt-bearer]]
  639. == JWT Bearer
  640. [NOTE]
  641. ====
  642. 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.
  643. ====
  644. [[oauth2-client-jwt-bearer-access-token]]
  645. === Requesting an Access Token
  646. [NOTE]
  647. ====
  648. 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.
  649. ====
  650. 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:
  651. * `DefaultJwtBearerTokenResponseClient` (_default_)
  652. * `RestClientJwtBearerTokenResponseClient`
  653. The default implementation uses a `RestOperations` instance to exchange an authorization code for an access token at the Authorization Server’s Token Endpoint.
  654. 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.
  655. [NOTE]
  656. ====
  657. This section focuses on `RestClientJwtBearerTokenResponseClient`.
  658. 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.
  659. ====
  660. :section-id: jwt-bearer
  661. :grant-type: JWT Bearer
  662. :class-name: RestClientJwtBearerTokenResponseClient
  663. :grant-request: JwtBearerGrantRequest
  664. :leveloffset: +1
  665. include::partial$servlet/oauth2/client/rest-client-access-token-response-client.adoc[]
  666. :leveloffset: -1
  667. [[oauth2-client-jwt-bearer-authorized-client-provider-builder]]
  668. === Customize using the Builder
  669. 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:
  670. .Access Token Response Configuration via Builder
  671. [tabs]
  672. ======
  673. Java::
  674. +
  675. [source,java,role="primary"]
  676. ----
  677. // Customize
  678. OAuth2AccessTokenResponseClient<JwtBearerGrantRequest> jwtBearerTokenResponseClient = ...
  679. JwtBearerOAuth2AuthorizedClientProvider jwtBearerAuthorizedClientProvider = new JwtBearerOAuth2AuthorizedClientProvider();
  680. jwtBearerAuthorizedClientProvider.setAccessTokenResponseClient(jwtBearerTokenResponseClient);
  681. OAuth2AuthorizedClientProvider authorizedClientProvider =
  682. OAuth2AuthorizedClientProviderBuilder.builder()
  683. .provider(jwtBearerAuthorizedClientProvider)
  684. .build();
  685. // ...
  686. authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
  687. ----
  688. Kotlin::
  689. +
  690. [source,kotlin,role="secondary"]
  691. ----
  692. // Customize
  693. val jwtBearerTokenResponseClient: OAuth2AccessTokenResponseClient<JwtBearerGrantRequest> = ...
  694. val jwtBearerAuthorizedClientProvider = JwtBearerOAuth2AuthorizedClientProvider()
  695. jwtBearerAuthorizedClientProvider.setAccessTokenResponseClient(jwtBearerTokenResponseClient)
  696. val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
  697. .provider(jwtBearerAuthorizedClientProvider)
  698. .build()
  699. // ...
  700. authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
  701. ----
  702. ======
  703. [[oauth2-client-jwt-bearer-authorized-client-manager]]
  704. === Using the Access Token
  705. Given the following Spring Boot properties for an OAuth 2.0 Client registration:
  706. [source,yaml]
  707. ----
  708. spring:
  709. security:
  710. oauth2:
  711. client:
  712. registration:
  713. okta:
  714. client-id: okta-client-id
  715. client-secret: okta-client-secret
  716. authorization-grant-type: urn:ietf:params:oauth:grant-type:jwt-bearer
  717. scope: read
  718. provider:
  719. okta:
  720. token-uri: https://dev-1234.oktapreview.com/oauth2/v1/token
  721. ----
  722. ...and the `OAuth2AuthorizedClientManager` `@Bean`:
  723. [tabs]
  724. ======
  725. Java::
  726. +
  727. [source,java,role="primary"]
  728. ----
  729. @Bean
  730. public OAuth2AuthorizedClientManager authorizedClientManager(
  731. ClientRegistrationRepository clientRegistrationRepository,
  732. OAuth2AuthorizedClientRepository authorizedClientRepository) {
  733. JwtBearerOAuth2AuthorizedClientProvider jwtBearerAuthorizedClientProvider =
  734. new JwtBearerOAuth2AuthorizedClientProvider();
  735. OAuth2AuthorizedClientProvider authorizedClientProvider =
  736. OAuth2AuthorizedClientProviderBuilder.builder()
  737. .provider(jwtBearerAuthorizedClientProvider)
  738. .build();
  739. DefaultOAuth2AuthorizedClientManager authorizedClientManager =
  740. new DefaultOAuth2AuthorizedClientManager(
  741. clientRegistrationRepository, authorizedClientRepository);
  742. authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
  743. return authorizedClientManager;
  744. }
  745. ----
  746. Kotlin::
  747. +
  748. [source,kotlin,role="secondary"]
  749. ----
  750. @Bean
  751. fun authorizedClientManager(
  752. clientRegistrationRepository: ClientRegistrationRepository,
  753. authorizedClientRepository: OAuth2AuthorizedClientRepository): OAuth2AuthorizedClientManager {
  754. val jwtBearerAuthorizedClientProvider = JwtBearerOAuth2AuthorizedClientProvider()
  755. val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
  756. .provider(jwtBearerAuthorizedClientProvider)
  757. .build()
  758. val authorizedClientManager = DefaultOAuth2AuthorizedClientManager(
  759. clientRegistrationRepository, authorizedClientRepository)
  760. authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
  761. return authorizedClientManager
  762. }
  763. ----
  764. ======
  765. You may obtain the `OAuth2AccessToken` as follows:
  766. [tabs]
  767. ======
  768. Java::
  769. +
  770. [source,java,role="primary"]
  771. ----
  772. @RestController
  773. public class OAuth2ResourceServerController {
  774. @Autowired
  775. private OAuth2AuthorizedClientManager authorizedClientManager;
  776. @GetMapping("/resource")
  777. public String resource(JwtAuthenticationToken jwtAuthentication) {
  778. OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("okta")
  779. .principal(jwtAuthentication)
  780. .build();
  781. OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest);
  782. OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
  783. // ...
  784. }
  785. }
  786. ----
  787. Kotlin::
  788. +
  789. [source,kotlin,role="secondary"]
  790. ----
  791. class OAuth2ResourceServerController {
  792. @Autowired
  793. private lateinit var authorizedClientManager: OAuth2AuthorizedClientManager
  794. @GetMapping("/resource")
  795. fun resource(jwtAuthentication: JwtAuthenticationToken?): String {
  796. val authorizeRequest: OAuth2AuthorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("okta")
  797. .principal(jwtAuthentication)
  798. .build()
  799. val authorizedClient = authorizedClientManager.authorize(authorizeRequest)
  800. val accessToken: OAuth2AccessToken = authorizedClient.accessToken
  801. // ...
  802. }
  803. }
  804. ----
  805. ======
  806. [NOTE]
  807. ====
  808. `JwtBearerOAuth2AuthorizedClientProvider` resolves the `Jwt` assertion via `OAuth2AuthorizationContext.getPrincipal().getPrincipal()` by default, hence the use of `JwtAuthenticationToken` in the preceding example.
  809. ====
  810. [TIP]
  811. ====
  812. If you need to resolve the `Jwt` assertion from a different source, you can provide `JwtBearerOAuth2AuthorizedClientProvider.setJwtAssertionResolver()` with a custom `Function<OAuth2AuthorizationContext, Jwt>`.
  813. ====
  814. [[oauth2-client-token-exchange]]
  815. == [[oauth2Client-token-exchange-grant]]Token Exchange
  816. [NOTE]
  817. ====
  818. Please refer to OAuth 2.0 Token Exchange for further details on the https://datatracker.ietf.org/doc/html/rfc8693[Token Exchange] grant.
  819. ====
  820. [[oauth2-client-token-exchange-access-token]]
  821. === Requesting an Access Token
  822. [NOTE]
  823. ====
  824. 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.
  825. ====
  826. 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:
  827. * `DefaultTokenExchangeTokenResponseClient` (_default_)
  828. * `RestClientTokenExchangeTokenResponseClient`
  829. The default implementation uses a `RestOperations` instance to exchange an authorization code for an access token at the Authorization Server’s Token Endpoint.
  830. 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.
  831. [NOTE]
  832. ====
  833. This section focuses on `RestClientTokenExchangeTokenResponseClient`.
  834. 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.
  835. ====
  836. :section-id: token-exchange
  837. :grant-type: Token Exchange
  838. :class-name: RestClientTokenExchangeTokenResponseClient
  839. :grant-request: TokenExchangeGrantRequest
  840. :leveloffset: +1
  841. include::partial$servlet/oauth2/client/rest-client-access-token-response-client.adoc[]
  842. :leveloffset: -1
  843. [[oauth2-client-token-exchange-authorized-client-provider-builder]]
  844. === Customize using the Builder
  845. 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:
  846. .Access Token Response Configuration via Builder
  847. [tabs]
  848. ======
  849. Java::
  850. +
  851. [source,java,role="primary"]
  852. ----
  853. // Customize
  854. OAuth2AccessTokenResponseClient<TokenExchangeGrantRequest> tokenExchangeTokenResponseClient = ...
  855. TokenExchangeOAuth2AuthorizedClientProvider tokenExchangeAuthorizedClientProvider = new TokenExchangeOAuth2AuthorizedClientProvider();
  856. tokenExchangeAuthorizedClientProvider.setAccessTokenResponseClient(tokenExchangeTokenResponseClient);
  857. OAuth2AuthorizedClientProvider authorizedClientProvider =
  858. OAuth2AuthorizedClientProviderBuilder.builder()
  859. .provider(tokenExchangeAuthorizedClientProvider)
  860. .build();
  861. // ...
  862. authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
  863. ----
  864. Kotlin::
  865. +
  866. [source,kotlin,role="secondary"]
  867. ----
  868. // Customize
  869. val tokenExchangeTokenResponseClient: OAuth2AccessTokenResponseClient<TokenExchangeGrantRequest> = ...
  870. val tokenExchangeAuthorizedClientProvider = TokenExchangeOAuth2AuthorizedClientProvider()
  871. tokenExchangeAuthorizedClientProvider.setAccessTokenResponseClient(tokenExchangeTokenResponseClient)
  872. val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
  873. .provider(tokenExchangeAuthorizedClientProvider)
  874. .build()
  875. // ...
  876. authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
  877. ----
  878. ======
  879. [[oauth2-client-token-exchange-authorized-client-manager]]
  880. === [[token-exchange-grant-access-token]]Using the Access Token
  881. Given the following Spring Boot properties for an OAuth 2.0 Client registration:
  882. [source,yaml]
  883. ----
  884. spring:
  885. security:
  886. oauth2:
  887. client:
  888. registration:
  889. okta:
  890. client-id: okta-client-id
  891. client-secret: okta-client-secret
  892. authorization-grant-type: urn:ietf:params:oauth:grant-type:token-exchange
  893. scope: read
  894. provider:
  895. okta:
  896. token-uri: https://dev-1234.oktapreview.com/oauth2/v1/token
  897. ----
  898. ...and the `OAuth2AuthorizedClientManager` `@Bean`:
  899. [tabs]
  900. ======
  901. Java::
  902. +
  903. [source,java,role="primary"]
  904. ----
  905. @Bean
  906. public OAuth2AuthorizedClientManager authorizedClientManager(
  907. ClientRegistrationRepository clientRegistrationRepository,
  908. OAuth2AuthorizedClientRepository authorizedClientRepository) {
  909. TokenExchangeOAuth2AuthorizedClientProvider tokenExchangeAuthorizedClientProvider =
  910. new TokenExchangeOAuth2AuthorizedClientProvider();
  911. OAuth2AuthorizedClientProvider authorizedClientProvider =
  912. OAuth2AuthorizedClientProviderBuilder.builder()
  913. .provider(tokenExchangeAuthorizedClientProvider)
  914. .build();
  915. DefaultOAuth2AuthorizedClientManager authorizedClientManager =
  916. new DefaultOAuth2AuthorizedClientManager(
  917. clientRegistrationRepository, authorizedClientRepository);
  918. authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
  919. return authorizedClientManager;
  920. }
  921. ----
  922. Kotlin::
  923. +
  924. [source,kotlin,role="secondary"]
  925. ----
  926. @Bean
  927. fun authorizedClientManager(
  928. clientRegistrationRepository: ClientRegistrationRepository,
  929. authorizedClientRepository: OAuth2AuthorizedClientRepository): OAuth2AuthorizedClientManager {
  930. val tokenExchangeAuthorizedClientProvider = TokenExchangeOAuth2AuthorizedClientProvider()
  931. val authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
  932. .provider(tokenExchangeAuthorizedClientProvider)
  933. .build()
  934. val authorizedClientManager = DefaultOAuth2AuthorizedClientManager(
  935. clientRegistrationRepository, authorizedClientRepository)
  936. authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider)
  937. return authorizedClientManager
  938. }
  939. ----
  940. ======
  941. You may obtain the `OAuth2AccessToken` as follows:
  942. [tabs]
  943. ======
  944. Java::
  945. +
  946. [source,java,role="primary"]
  947. ----
  948. @RestController
  949. public class OAuth2ResourceServerController {
  950. @Autowired
  951. private OAuth2AuthorizedClientManager authorizedClientManager;
  952. @GetMapping("/resource")
  953. public String resource(JwtAuthenticationToken jwtAuthentication) {
  954. OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("okta")
  955. .principal(jwtAuthentication)
  956. .build();
  957. OAuth2AuthorizedClient authorizedClient = this.authorizedClientManager.authorize(authorizeRequest);
  958. OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
  959. // ...
  960. }
  961. }
  962. ----
  963. Kotlin::
  964. +
  965. [source,kotlin,role="secondary"]
  966. ----
  967. class OAuth2ResourceServerController {
  968. @Autowired
  969. private lateinit var authorizedClientManager: OAuth2AuthorizedClientManager
  970. @GetMapping("/resource")
  971. fun resource(jwtAuthentication: JwtAuthenticationToken?): String {
  972. val authorizeRequest: OAuth2AuthorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("okta")
  973. .principal(jwtAuthentication)
  974. .build()
  975. val authorizedClient = authorizedClientManager.authorize(authorizeRequest)
  976. val accessToken: OAuth2AccessToken = authorizedClient.accessToken
  977. // ...
  978. }
  979. }
  980. ----
  981. ======
  982. [NOTE]
  983. ====
  984. `TokenExchangeOAuth2AuthorizedClientProvider` resolves the subject token (as an `OAuth2Token`) via `OAuth2AuthorizationContext.getPrincipal().getPrincipal()` by default, hence the use of `JwtAuthenticationToken` in the preceding example.
  985. An actor token is not resolved by default.
  986. ====
  987. [TIP]
  988. ====
  989. If you need to resolve the subject token from a different source, you can provide `TokenExchangeOAuth2AuthorizedClientProvider.setSubjectTokenResolver()` with a custom `Function<OAuth2AuthorizationContext, OAuth2Token>`.
  990. ====
  991. [TIP]
  992. ====
  993. If you need to resolve an actor token, you can provide `TokenExchangeOAuth2AuthorizedClientProvider.setActorTokenResolver()` with a custom `Function<OAuth2AuthorizationContext, OAuth2Token>`.
  994. ====