protocol-endpoints.adoc 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921
  1. [[protocol-endpoints]]
  2. = Protocol Endpoints
  3. [[oauth2-authorization-endpoint]]
  4. == OAuth2 Authorization Endpoint
  5. `OAuth2AuthorizationEndpointConfigurer` provides the ability to customize the https://datatracker.ietf.org/doc/html/rfc6749#section-3.1[OAuth2 Authorization endpoint].
  6. It defines extension points that let you customize the pre-processing, main processing, and post-processing logic for https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.1[OAuth2 authorization requests].
  7. `OAuth2AuthorizationEndpointConfigurer` provides the following configuration options:
  8. [source,java]
  9. ----
  10. @Bean
  11. public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
  12. OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
  13. OAuth2AuthorizationServerConfigurer.authorizationServer();
  14. http
  15. .securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
  16. .with(authorizationServerConfigurer, (authorizationServer) ->
  17. authorizationServer
  18. .authorizationEndpoint(authorizationEndpoint ->
  19. authorizationEndpoint
  20. .authorizationRequestConverter(authorizationRequestConverter) <1>
  21. .authorizationRequestConverters(authorizationRequestConvertersConsumer) <2>
  22. .authenticationProvider(authenticationProvider) <3>
  23. .authenticationProviders(authenticationProvidersConsumer) <4>
  24. .authorizationResponseHandler(authorizationResponseHandler) <5>
  25. .errorResponseHandler(errorResponseHandler) <6>
  26. .consentPage("/oauth2/v1/authorize") <7>
  27. )
  28. );
  29. return http.build();
  30. }
  31. ----
  32. <1> `authorizationRequestConverter()`: Adds an `AuthenticationConverter` (_pre-processor_) used when attempting to extract an https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.1[OAuth2 authorization request] (or consent) from `HttpServletRequest` to an instance of `OAuth2AuthorizationCodeRequestAuthenticationToken` or `OAuth2AuthorizationConsentAuthenticationToken`.
  33. <2> `authorizationRequestConverters()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationConverter``'s allowing the ability to add, remove, or customize a specific `AuthenticationConverter`.
  34. <3> `authenticationProvider()`: Adds an `AuthenticationProvider` (_main processor_) used for authenticating the `OAuth2AuthorizationCodeRequestAuthenticationToken` or `OAuth2AuthorizationConsentAuthenticationToken`.
  35. <4> `authenticationProviders()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationProvider``'s allowing the ability to add, remove, or customize a specific `AuthenticationProvider`.
  36. <5> `authorizationResponseHandler()`: The `AuthenticationSuccessHandler` (_post-processor_) used for handling an "`authenticated`" `OAuth2AuthorizationCodeRequestAuthenticationToken` and returning the https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2[OAuth2AuthorizationResponse].
  37. <6> `errorResponseHandler()`: The `AuthenticationFailureHandler` (_post-processor_) used for handling an `OAuth2AuthorizationCodeRequestAuthenticationException` and returning the https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2.1[OAuth2Error response].
  38. <7> `consentPage()`: The `URI` of the custom consent page to redirect resource owners to if consent is required during the authorization request flow.
  39. `OAuth2AuthorizationEndpointConfigurer` configures the `OAuth2AuthorizationEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
  40. `OAuth2AuthorizationEndpointFilter` is the `Filter` that processes OAuth2 authorization requests (and consents).
  41. `OAuth2AuthorizationEndpointFilter` is configured with the following defaults:
  42. * `*AuthenticationConverter*` -- A `DelegatingAuthenticationConverter` composed of `OAuth2AuthorizationCodeRequestAuthenticationConverter` and `OAuth2AuthorizationConsentAuthenticationConverter`.
  43. * `*AuthenticationManager*` -- An `AuthenticationManager` composed of `OAuth2AuthorizationCodeRequestAuthenticationProvider` and `OAuth2AuthorizationConsentAuthenticationProvider`.
  44. * `*AuthenticationSuccessHandler*` -- An internal implementation that handles an "`authenticated`" `OAuth2AuthorizationCodeRequestAuthenticationToken` and returns the `OAuth2AuthorizationResponse`.
  45. * `*AuthenticationFailureHandler*` -- An internal implementation that uses the `OAuth2Error` associated with the `OAuth2AuthorizationCodeRequestAuthenticationException` and returns the `OAuth2Error` response.
  46. [[oauth2-authorization-endpoint-customizing-authorization-request-validation]]
  47. === Customizing Authorization Request Validation
  48. `OAuth2AuthorizationCodeRequestAuthenticationValidator` is the default validator used for validating specific OAuth2 authorization request parameters used in the Authorization Code Grant.
  49. The default implementation validates the `redirect_uri` and `scope` parameters.
  50. If validation fails, an `OAuth2AuthorizationCodeRequestAuthenticationException` is thrown.
  51. `OAuth2AuthorizationCodeRequestAuthenticationProvider` provides the ability to override the default authorization request validation by supplying a custom authentication validator of type `Consumer<OAuth2AuthorizationCodeRequestAuthenticationContext>` to `setAuthenticationValidator()`.
  52. [TIP]
  53. `OAuth2AuthorizationCodeRequestAuthenticationContext` holds the `OAuth2AuthorizationCodeRequestAuthenticationToken`, which contains the OAuth2 authorization request parameters.
  54. [IMPORTANT]
  55. If validation fails, the authentication validator *MUST* throw `OAuth2AuthorizationCodeRequestAuthenticationException`.
  56. A common use case during the development life cycle phase is to allow for `localhost` in the `redirect_uri` parameter.
  57. The following example shows how to configure `OAuth2AuthorizationCodeRequestAuthenticationProvider` with a custom authentication validator that allows for `localhost` in the `redirect_uri` parameter:
  58. [source,java]
  59. ----
  60. @Bean
  61. public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
  62. OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
  63. OAuth2AuthorizationServerConfigurer.authorizationServer();
  64. http
  65. .securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
  66. .with(authorizationServerConfigurer, (authorizationServer) ->
  67. authorizationServer
  68. .authorizationEndpoint(authorizationEndpoint ->
  69. authorizationEndpoint
  70. .authenticationProviders(configureAuthenticationValidator())
  71. )
  72. );
  73. return http.build();
  74. }
  75. private Consumer<List<AuthenticationProvider>> configureAuthenticationValidator() {
  76. return (authenticationProviders) ->
  77. authenticationProviders.forEach((authenticationProvider) -> {
  78. if (authenticationProvider instanceof OAuth2AuthorizationCodeRequestAuthenticationProvider) {
  79. Consumer<OAuth2AuthorizationCodeRequestAuthenticationContext> authenticationValidator =
  80. // Override default redirect_uri validator
  81. new CustomRedirectUriValidator()
  82. // Reuse default scope validator
  83. .andThen(OAuth2AuthorizationCodeRequestAuthenticationValidator.DEFAULT_SCOPE_VALIDATOR);
  84. ((OAuth2AuthorizationCodeRequestAuthenticationProvider) authenticationProvider)
  85. .setAuthenticationValidator(authenticationValidator);
  86. }
  87. });
  88. }
  89. static class CustomRedirectUriValidator implements Consumer<OAuth2AuthorizationCodeRequestAuthenticationContext> {
  90. @Override
  91. public void accept(OAuth2AuthorizationCodeRequestAuthenticationContext authenticationContext) {
  92. OAuth2AuthorizationCodeRequestAuthenticationToken authorizationCodeRequestAuthentication =
  93. authenticationContext.getAuthentication();
  94. RegisteredClient registeredClient = authenticationContext.getRegisteredClient();
  95. String requestedRedirectUri = authorizationCodeRequestAuthentication.getRedirectUri();
  96. // Use exact string matching when comparing client redirect URIs against pre-registered URIs
  97. if (!registeredClient.getRedirectUris().contains(requestedRedirectUri)) {
  98. OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST);
  99. throw new OAuth2AuthorizationCodeRequestAuthenticationException(error, null);
  100. }
  101. }
  102. }
  103. ----
  104. [[oauth2-device-authorization-endpoint]]
  105. == OAuth2 Device Authorization Endpoint
  106. `OAuth2DeviceAuthorizationEndpointConfigurer` provides the ability to customize the https://datatracker.ietf.org/doc/html/rfc8628#section-3.1[OAuth2 Device Authorization endpoint].
  107. It defines extension points that let you customize the pre-processing, main processing, and post-processing logic for OAuth2 device authorization requests.
  108. `OAuth2DeviceAuthorizationEndpointConfigurer` provides the following configuration options:
  109. [source,java]
  110. ----
  111. @Bean
  112. public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
  113. OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
  114. OAuth2AuthorizationServerConfigurer.authorizationServer();
  115. http
  116. .securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
  117. .with(authorizationServerConfigurer, (authorizationServer) ->
  118. authorizationServer
  119. .deviceAuthorizationEndpoint(deviceAuthorizationEndpoint ->
  120. deviceAuthorizationEndpoint
  121. .deviceAuthorizationRequestConverter(deviceAuthorizationRequestConverter) <1>
  122. .deviceAuthorizationRequestConverters(deviceAuthorizationRequestConvertersConsumer) <2>
  123. .authenticationProvider(authenticationProvider) <3>
  124. .authenticationProviders(authenticationProvidersConsumer) <4>
  125. .deviceAuthorizationResponseHandler(deviceAuthorizationResponseHandler) <5>
  126. .errorResponseHandler(errorResponseHandler) <6>
  127. .verificationUri("/oauth2/v1/device_verification") <7>
  128. )
  129. );
  130. return http.build();
  131. }
  132. ----
  133. <1> `deviceAuthorizationRequestConverter()`: Adds an `AuthenticationConverter` (_pre-processor_) used when attempting to extract an https://datatracker.ietf.org/doc/html/rfc8628#section-3.1[OAuth2 device authorization request] from `HttpServletRequest` to an instance of `OAuth2DeviceAuthorizationRequestAuthenticationToken`.
  134. <2> `deviceAuthorizationRequestConverters()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationConverter``'s allowing the ability to add, remove, or customize a specific `AuthenticationConverter`.
  135. <3> `authenticationProvider()`: Adds an `AuthenticationProvider` (_main processor_) used for authenticating the `OAuth2DeviceAuthorizationRequestAuthenticationToken`.
  136. <4> `authenticationProviders()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationProvider``'s allowing the ability to add, remove, or customize a specific `AuthenticationProvider`.
  137. <5> `deviceAuthorizationResponseHandler()`: The `AuthenticationSuccessHandler` (_post-processor_) used for handling an "`authenticated`" `OAuth2DeviceAuthorizationRequestAuthenticationToken` and returning the https://datatracker.ietf.org/doc/html/rfc8628#section-3.2[OAuth2DeviceAuthorizationResponse].
  138. <6> `errorResponseHandler()`: The `AuthenticationFailureHandler` (_post-processor_) used for handling an `OAuth2AuthenticationException` and returning the https://datatracker.ietf.org/doc/html/rfc6749#section-5.2[OAuth2Error response].
  139. <7> `verificationUri()`: The `URI` of the custom end-user verification page to direct resource owners to on a secondary device.
  140. `OAuth2DeviceAuthorizationEndpointConfigurer` configures the `OAuth2DeviceAuthorizationEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
  141. `OAuth2DeviceAuthorizationEndpointFilter` is the `Filter` that processes OAuth2 device authorization requests.
  142. `OAuth2DeviceAuthorizationEndpointFilter` is configured with the following defaults:
  143. * `*AuthenticationConverter*` -- An `OAuth2DeviceAuthorizationRequestAuthenticationConverter`.
  144. * `*AuthenticationManager*` -- An `AuthenticationManager` composed of `OAuth2DeviceAuthorizationRequestAuthenticationProvider`.
  145. * `*AuthenticationSuccessHandler*` -- An internal implementation that handles an "`authenticated`" `OAuth2DeviceAuthorizationRequestAuthenticationToken` and returns the `OAuth2DeviceAuthorizationResponse`.
  146. * `*AuthenticationFailureHandler*` -- An `OAuth2ErrorAuthenticationFailureHandler`.
  147. [[oauth2-device-verification-endpoint]]
  148. == OAuth2 Device Verification Endpoint
  149. `OAuth2DeviceVerificationEndpointConfigurer` provides the ability to customize the https://datatracker.ietf.org/doc/html/rfc8628#section-3.3[OAuth2 Device Verification endpoint] (or "User Interaction").
  150. It defines extension points that let you customize the pre-processing, main processing, and post-processing logic for OAuth2 device verification requests.
  151. `OAuth2DeviceVerificationEndpointConfigurer` provides the following configuration options:
  152. [source,java]
  153. ----
  154. @Bean
  155. public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
  156. OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
  157. OAuth2AuthorizationServerConfigurer.authorizationServer();
  158. http
  159. .securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
  160. .with(authorizationServerConfigurer, (authorizationServer) ->
  161. authorizationServer
  162. .deviceVerificationEndpoint(deviceVerificationEndpoint ->
  163. deviceVerificationEndpoint
  164. .deviceVerificationRequestConverter(deviceVerificationRequestConverter) <1>
  165. .deviceVerificationRequestConverters(deviceVerificationRequestConvertersConsumer) <2>
  166. .authenticationProvider(authenticationProvider) <3>
  167. .authenticationProviders(authenticationProvidersConsumer) <4>
  168. .deviceVerificationResponseHandler(deviceVerificationResponseHandler) <5>
  169. .errorResponseHandler(errorResponseHandler) <6>
  170. .consentPage("/oauth2/v1/consent") <7>
  171. )
  172. );
  173. return http.build();
  174. }
  175. ----
  176. <1> `deviceVerificationRequestConverter()`: Adds an `AuthenticationConverter` (_pre-processor_) used when attempting to extract an https://datatracker.ietf.org/doc/html/rfc8628#section-3.3[OAuth2 device verification request] (or consent) from `HttpServletRequest` to an instance of `OAuth2DeviceVerificationAuthenticationToken` or `OAuth2DeviceAuthorizationConsentAuthenticationToken`.
  177. <2> `deviceVerificationRequestConverters()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationConverter``'s allowing the ability to add, remove, or customize a specific `AuthenticationConverter`.
  178. <3> `authenticationProvider()`: Adds an `AuthenticationProvider` (_main processor_) used for authenticating the `OAuth2DeviceVerificationAuthenticationToken` or `OAuth2DeviceAuthorizationConsentAuthenticationToken`.
  179. <4> `authenticationProviders()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationProvider``'s allowing the ability to add, remove, or customize a specific `AuthenticationProvider`.
  180. <5> `deviceVerificationResponseHandler()`: The `AuthenticationSuccessHandler` (_post-processor_) used for handling an "`authenticated`" `OAuth2DeviceVerificationAuthenticationToken` and directing the resource owner to return to their device.
  181. <6> `errorResponseHandler()`: The `AuthenticationFailureHandler` (_post-processor_) used for handling an `OAuth2AuthenticationException` and returning the error response.
  182. <7> `consentPage()`: The `URI` of the custom consent page to redirect resource owners to if consent is required during the device verification request flow.
  183. `OAuth2DeviceVerificationEndpointConfigurer` configures the `OAuth2DeviceVerificationEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
  184. `OAuth2DeviceVerificationEndpointFilter` is the `Filter` that processes OAuth2 device verification requests (and consents).
  185. `OAuth2DeviceVerificationEndpointFilter` is configured with the following defaults:
  186. * `*AuthenticationConverter*` -- A `DelegatingAuthenticationConverter` composed of `OAuth2DeviceVerificationAuthenticationConverter` and `OAuth2DeviceAuthorizationConsentAuthenticationConverter`.
  187. * `*AuthenticationManager*` -- An `AuthenticationManager` composed of `OAuth2DeviceVerificationAuthenticationProvider` and `OAuth2DeviceAuthorizationConsentAuthenticationProvider`.
  188. * `*AuthenticationSuccessHandler*` -- A `SimpleUrlAuthenticationSuccessHandler` that handles an "`authenticated`" `OAuth2DeviceVerificationAuthenticationToken` and redirects the user to a success page (`/?success`).
  189. * `*AuthenticationFailureHandler*` -- An internal implementation that uses the `OAuth2Error` associated with the `OAuth2AuthenticationException` and returns the `OAuth2Error` response.
  190. [[oauth2-token-endpoint]]
  191. == OAuth2 Token Endpoint
  192. `OAuth2TokenEndpointConfigurer` provides the ability to customize the https://datatracker.ietf.org/doc/html/rfc6749#section-3.2[OAuth2 Token endpoint].
  193. It defines extension points that let you customize the pre-processing, main processing, and post-processing logic for https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.3[OAuth2 access token requests].
  194. `OAuth2TokenEndpointConfigurer` provides the following configuration options:
  195. [source,java]
  196. ----
  197. @Bean
  198. public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
  199. OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
  200. OAuth2AuthorizationServerConfigurer.authorizationServer();
  201. http
  202. .securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
  203. .with(authorizationServerConfigurer, (authorizationServer) ->
  204. authorizationServer
  205. .tokenEndpoint(tokenEndpoint ->
  206. tokenEndpoint
  207. .accessTokenRequestConverter(accessTokenRequestConverter) <1>
  208. .accessTokenRequestConverters(accessTokenRequestConvertersConsumer) <2>
  209. .authenticationProvider(authenticationProvider) <3>
  210. .authenticationProviders(authenticationProvidersConsumer) <4>
  211. .accessTokenResponseHandler(accessTokenResponseHandler) <5>
  212. .errorResponseHandler(errorResponseHandler) <6>
  213. )
  214. );
  215. return http.build();
  216. }
  217. ----
  218. <1> `accessTokenRequestConverter()`: Adds an `AuthenticationConverter` (_pre-processor_) used when attempting to extract an https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.3[OAuth2 access token request] from `HttpServletRequest` to an instance of `OAuth2AuthorizationGrantAuthenticationToken`.
  219. <2> `accessTokenRequestConverters()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationConverter``'s allowing the ability to add, remove, or customize a specific `AuthenticationConverter`.
  220. <3> `authenticationProvider()`: Adds an `AuthenticationProvider` (_main processor_) used for authenticating the `OAuth2AuthorizationGrantAuthenticationToken`.
  221. <4> `authenticationProviders()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationProvider``'s allowing the ability to add, remove, or customize a specific `AuthenticationProvider`.
  222. <5> `accessTokenResponseHandler()`: The `AuthenticationSuccessHandler` (_post-processor_) used for handling an `OAuth2AccessTokenAuthenticationToken` and returning the https://datatracker.ietf.org/doc/html/rfc6749#section-5.1[`OAuth2AccessTokenResponse`].
  223. <6> `errorResponseHandler()`: The `AuthenticationFailureHandler` (_post-processor_) used for handling an `OAuth2AuthenticationException` and returning the https://datatracker.ietf.org/doc/html/rfc6749#section-5.2[OAuth2Error response].
  224. `OAuth2TokenEndpointConfigurer` configures the `OAuth2TokenEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
  225. `OAuth2TokenEndpointFilter` is the `Filter` that processes OAuth2 access token requests.
  226. The supported https://datatracker.ietf.org/doc/html/rfc6749#section-1.3[authorization grant types] are `authorization_code`, `refresh_token`, `client_credentials`, `urn:ietf:params:oauth:grant-type:device_code`, and `urn:ietf:params:oauth:grant-type:token-exchange`.
  227. `OAuth2TokenEndpointFilter` is configured with the following defaults:
  228. * `*AuthenticationConverter*` -- A `DelegatingAuthenticationConverter` composed of `OAuth2AuthorizationCodeAuthenticationConverter`, `OAuth2RefreshTokenAuthenticationConverter`, `OAuth2ClientCredentialsAuthenticationConverter`, `OAuth2DeviceCodeAuthenticationConverter`, and `OAuth2TokenExchangeAuthenticationConverter`.
  229. * `*AuthenticationManager*` -- An `AuthenticationManager` composed of `OAuth2AuthorizationCodeAuthenticationProvider`, `OAuth2RefreshTokenAuthenticationProvider`, `OAuth2ClientCredentialsAuthenticationProvider`, `OAuth2DeviceCodeAuthenticationProvider`, and `OAuth2TokenExchangeAuthenticationProvider`.
  230. * `*AuthenticationSuccessHandler*` -- An `OAuth2AccessTokenResponseAuthenticationSuccessHandler`.
  231. * `*AuthenticationFailureHandler*` -- An `OAuth2ErrorAuthenticationFailureHandler`.
  232. [[oauth2-token-endpoint-customizing-client-credentials-grant-request-validation]]
  233. === Customizing Client Credentials Grant Request Validation
  234. `OAuth2ClientCredentialsAuthenticationValidator` is the default validator used for validating specific OAuth2 Client Credentials Grant request parameters.
  235. The default implementation validates the `scope` parameter.
  236. If validation fails, an `OAuth2AuthenticationException` is thrown.
  237. `OAuth2ClientCredentialsAuthenticationProvider` provides the ability to override the default request validation by supplying a custom authentication validator of type `Consumer<OAuth2ClientCredentialsAuthenticationContext>` to `setAuthenticationValidator()`.
  238. [TIP]
  239. `OAuth2ClientCredentialsAuthenticationContext` holds the `OAuth2ClientCredentialsAuthenticationToken`, which contains the OAuth2 Client Credentials Grant request parameters.
  240. [IMPORTANT]
  241. If validation fails, the authentication validator *MUST* throw `OAuth2AuthenticationException`.
  242. The following example shows how to configure `OAuth2ClientCredentialsAuthenticationProvider` with a custom authentication validator that overrides the default `scope` validation:
  243. [source,java]
  244. ----
  245. @Bean
  246. public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
  247. OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
  248. OAuth2AuthorizationServerConfigurer.authorizationServer();
  249. http
  250. .securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
  251. .with(authorizationServerConfigurer, (authorizationServer) ->
  252. authorizationServer
  253. .tokenEndpoint(tokenEndpoint ->
  254. tokenEndpoint
  255. .authenticationProviders(configureAuthenticationValidator())
  256. )
  257. );
  258. return http.build();
  259. }
  260. private Consumer<List<AuthenticationProvider>> configureAuthenticationValidator() {
  261. return (authenticationProviders) ->
  262. authenticationProviders.forEach((authenticationProvider) -> {
  263. if (authenticationProvider instanceof OAuth2ClientCredentialsAuthenticationProvider) {
  264. Consumer<OAuth2ClientCredentialsAuthenticationContext> authenticationValidator =
  265. new CustomScopeValidator();
  266. // Override default scope validation
  267. ((OAuth2ClientCredentialsAuthenticationProvider) authenticationProvider)
  268. .setAuthenticationValidator(authenticationValidator);
  269. }
  270. });
  271. }
  272. static class CustomScopeValidator implements Consumer<OAuth2ClientCredentialsAuthenticationContext> {
  273. @Override
  274. public void accept(OAuth2ClientCredentialsAuthenticationContext authenticationContext) {
  275. OAuth2ClientCredentialsAuthenticationToken clientCredentialsAuthentication =
  276. authenticationContext.getAuthentication();
  277. Set<String> requestedScopes = clientCredentialsAuthentication.getScopes();
  278. RegisteredClient registeredClient = authenticationContext.getRegisteredClient();
  279. Set<String> allowedScopes = registeredClient.getScopes();
  280. // TODO Implement scope validation
  281. }
  282. }
  283. ----
  284. [[oauth2-token-endpoint-dpop-bound-access-tokens]]
  285. === DPoP-bound Access Tokens
  286. https://datatracker.ietf.org/doc/html/rfc9449[RFC 9449 OAuth 2.0 Demonstrating Proof of Possession (DPoP)] is an application-level mechanism for sender-constraining an access token.
  287. The primary goal of DPoP is to prevent unauthorized or illegitimate clients from using leaked or stolen access tokens, by binding an access token to a public key upon issuance by the authorization server and requiring that the client proves possession of the corresponding private key when using the access token at the resource server.
  288. Access tokens that are sender-constrained via DPoP stand in contrast to the typical bearer token, which can be used by any client in possession of the access token.
  289. DPoP introduces the concept of a https://datatracker.ietf.org/doc/html/rfc9449#name-dpop-proof-jwts[DPoP Proof], which is a JWT created by the client and sent as a header in an HTTP request.
  290. A client uses a DPoP proof to prove the possession of a private key corresponding to a certain public key.
  291. When the client initiates an access token request, it attaches a DPoP proof to the request in an HTTP header.
  292. The authorization server binds (sender-constrains) the access token to the public key associated in the DPoP proof.
  293. When the client initiates a protected resource request, it again attaches a DPoP proof to the request in an HTTP header.
  294. The resource server obtains information about the public key bound to the access token, either directly in the access token (JWT) or via the <<oauth2-token-introspection-endpoint,OAuth2 Token Introspection endpoint>>.
  295. The resource server then verifies that the public key bound to the access token matches the public key in the DPoP proof.
  296. It also verifies that the access token hash in the DPoP proof matches the access token in the request.
  297. [[oauth2-token-endpoint-dpop-access-token-request]]
  298. ==== DPoP Access Token Request
  299. To request an access token that is bound to a public key using DPoP, the client MUST provide a valid DPoP proof in the `DPoP` header when making an access token request to the OAuth2 Token endpoint.
  300. This is applicable for all access token requests regardless of authorization grant type (e.g. `authorization_code`, `refresh_token`, `client_credentials`, etc).
  301. The following HTTP request shows an `authorization_code` access token request with a DPoP proof in the `DPoP` header:
  302. [source,shell]
  303. ----
  304. POST /oauth2/token HTTP/1.1
  305. Host: server.example.com
  306. Content-Type: application/x-www-form-urlencoded
  307. DPoP: eyJraWQiOiJyc2EtandrLWtpZCIsInR5cCI6ImRwb3Arand0IiwiYWxnIjoiUlMyNTYiLCJqd2siOnsia3R5IjoiUlNBIiwiZSI6IkFRQUIiLCJraWQiOiJyc2EtandrLWtpZCIsIm4iOiIzRmxxSnI1VFJza0lRSWdkRTNEZDdEOWxib1dkY1RVVDhhLWZKUjdNQXZRbTdYWE5vWWttM3Y3TVFMMU5ZdER2TDJsOENBbmMwV2RTVElOVTZJUnZjNUtxbzJRNGNzTlg5U0hPbUVmem9ST2pRcWFoRWN2ZTFqQlhsdW9DWGRZdVlweDRfMXRmUmdHNmlpNFVoeGg2aUk4cU5NSlFYLWZMZnFoYmZZZnhCUVZSUHl3QmtBYklQNHgxRUFzYkM2RlNObWtoQ3hpTU5xRWd4YUlwWThDMmtKZEpfWklWLVdXNG5vRGR6cEtxSGN3bUI4RnNydW1sVllfRE5WdlVTRElpcGlxOVBiUDRIOTlUWE4xbzc0Nm9SYU5hMDdycTFob0NnTVNTeS04NVNhZ0NveGxteUUtRC1vZjlTc01ZOE9sOXQwcmR6cG9iQnVoeUpfbzVkZnZqS3cifX0.eyJodG0iOiJQT1NUIiwiaHR1IjoiaHR0cHM6Ly9zZXJ2ZXIuZXhhbXBsZS5jb20vb2F1dGgyL3Rva2VuIiwiaWF0IjoxNzQ2ODA2MzA1LCJqdGkiOiI0YjIzNDBkMi1hOTFmLTQwYTUtYmFhOS1kZDRlNWRlYWM4NjcifQ.wq8gJ_G6vpiEinfaY3WhereqCCLoeJOG8tnWBBAzRWx9F1KU5yAAWq-ZVCk_k07-h6DIqz2wgv6y9dVbNpRYwNwDUeik9qLRsC60M8YW7EFVyI3n_NpujLwzZeub_nDYMVnyn4ii0NaZrYHtoGXOlswQfS_-ET-jpC0XWm5nBZsCdUEXjOYtwaACC6Js-pyNwKmSLp5SKIk11jZUR5xIIopaQy521y9qJHhGRwzj8DQGsP7wMZ98UFL0E--1c-hh4rTy8PMeWCqRHdwjj_ry_eTe0DJFcxxYQdeL7-0_0CIO4Ayx5WHEpcUOIzBRoN32RsNpDZc-5slDNj9ku004DA
  308. grant_type=authorization_code\
  309. &client_id=s6BhdRkqt\
  310. &code=SplxlOBeZQQYbYS6WxSbIA\
  311. &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb\
  312. &code_verifier=bEaL42izcC-o-xBk0K2vuJ6U-y1p9r_wW2dFWIWgjz-
  313. ----
  314. The following shows a representation of the DPoP Proof JWT header and claims:
  315. [source,json]
  316. ----
  317. {
  318. "typ": "dpop+jwt",
  319. "alg": "RS256",
  320. "jwk": {
  321. "kty": "RSA",
  322. "e": "AQAB",
  323. "n": "3FlqJr5TRskIQIgdE3Dd7D9lboWdcTUT8a-fJR7MAvQm7XXNoYkm3v7MQL1NYtDvL2l8CAnc0WdSTINU6IRvc5Kqo2Q4csNX9SHOmEfzoROjQqahEcve1jBXluoCXdYuYpx4_1tfRgG6ii4Uhxh6iI8qNMJQX-fLfqhbfYfxBQVRPywBkAbIP4x1EAsbC6FSNmkhCxiMNqEgxaIpY8C2kJdJ_ZIV-WW4noDdzpKqHcwmB8FsrumlVY_DNVvUSDIipiq9PbP4H99TXN1o746oRaNa07rq1hoCgMSSy-85SagCoxlmyE-D-of9SsMY8Ol9t0rdzpobBuhyJ_o5dfvjKw"
  324. }
  325. }
  326. ----
  327. [source,json]
  328. ----
  329. {
  330. "htm": "POST",
  331. "htu": "https://server.example.com/oauth2/token",
  332. "iat": 1746806305,
  333. "jti": "4b2340d2-a91f-40a5-baa9-dd4e5deac867"
  334. }
  335. ----
  336. The following code shows an example of how to generate the DPoP Proof JWT:
  337. [source,java]
  338. ----
  339. RSAKey rsaKey = ...
  340. JWKSource<SecurityContext> jwkSource = (jwkSelector, securityContext) -> jwkSelector
  341. .select(new JWKSet(rsaKey));
  342. NimbusJwtEncoder jwtEncoder = new NimbusJwtEncoder(jwkSource);
  343. JwsHeader jwsHeader = JwsHeader.with(SignatureAlgorithm.RS256)
  344. .type("dpop+jwt")
  345. .jwk(rsaKey.toPublicJWK().toJSONObject())
  346. .build();
  347. JwtClaimsSet claims = JwtClaimsSet.builder()
  348. .issuedAt(Instant.now())
  349. .claim("htm", "POST")
  350. .claim("htu", "https://server.example.com/oauth2/token")
  351. .id(UUID.randomUUID().toString())
  352. .build();
  353. Jwt dPoPProof = jwtEncoder.encode(JwtEncoderParameters.from(jwsHeader, claims));
  354. ----
  355. After the authorization server successfully validates the DPoP proof, the public key from the DPoP proof will be bound (sender-constrained) to the issued access token.
  356. The following access token response shows the `token_type` parameter as `DPoP` to signal to the client that the access token was bound to its DPoP proof public key:
  357. [source,shell]
  358. ----
  359. HTTP/1.1 200 OK
  360. Content-Type: application/json
  361. Cache-Control: no-store
  362. {
  363. "access_token": "Kz~8mXK1EalYznwH-LC-1fBAo.4Ljp~zsPE_NeO.gxU",
  364. "token_type": "DPoP",
  365. "expires_in": 2677
  366. }
  367. ----
  368. [[oauth2-token-endpoint-dpop-public-key-confirmation]]
  369. ==== Public Key Confirmation
  370. Resource servers MUST be able to identify whether an access token is DPoP-bound and verify the binding to the public key of the DPoP proof.
  371. The binding is accomplished by associating the public key with the access token in a way that can be accessed by the resource server, such as embedding the public key hash in the access token directly (JWT) or through token introspection.
  372. When an access token is represented as a JWT, the public key hash is contained in the `jkt` claim under the confirmation method (`cnf`) claim.
  373. The following example shows the claims of a JWT access token containing a `cnf` claim with a `jkt` claim, which is the JWK SHA-256 Thumbprint of the DPoP proof public key:
  374. [source,json]
  375. ----
  376. {
  377. "sub":"user@example.com",
  378. "iss":"https://server.example.com",
  379. "nbf":1562262611,
  380. "exp":1562266216,
  381. "cnf":
  382. {
  383. "jkt":"CQMknzRoZ5YUi7vS58jck1q8TmZT8wiIiXrCN1Ny4VU"
  384. }
  385. }
  386. ----
  387. [[oauth2-token-introspection-endpoint]]
  388. == OAuth2 Token Introspection Endpoint
  389. `OAuth2TokenIntrospectionEndpointConfigurer` provides the ability to customize the https://datatracker.ietf.org/doc/html/rfc7662#section-2[OAuth2 Token Introspection endpoint].
  390. It defines extension points that let you customize the pre-processing, main processing, and post-processing logic for https://datatracker.ietf.org/doc/html/rfc7662#section-2.1[OAuth2 introspection requests].
  391. `OAuth2TokenIntrospectionEndpointConfigurer` provides the following configuration options:
  392. [source,java]
  393. ----
  394. @Bean
  395. public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
  396. OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
  397. OAuth2AuthorizationServerConfigurer.authorizationServer();
  398. http
  399. .securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
  400. .with(authorizationServerConfigurer, (authorizationServer) ->
  401. authorizationServer
  402. .tokenIntrospectionEndpoint(tokenIntrospectionEndpoint ->
  403. tokenIntrospectionEndpoint
  404. .introspectionRequestConverter(introspectionRequestConverter) <1>
  405. .introspectionRequestConverters(introspectionRequestConvertersConsumer) <2>
  406. .authenticationProvider(authenticationProvider) <3>
  407. .authenticationProviders(authenticationProvidersConsumer) <4>
  408. .introspectionResponseHandler(introspectionResponseHandler) <5>
  409. .errorResponseHandler(errorResponseHandler) <6>
  410. )
  411. );
  412. return http.build();
  413. }
  414. ----
  415. <1> `introspectionRequestConverter()`: Adds an `AuthenticationConverter` (_pre-processor_) used when attempting to extract an https://datatracker.ietf.org/doc/html/rfc7662#section-2.1[OAuth2 introspection request] from `HttpServletRequest` to an instance of `OAuth2TokenIntrospectionAuthenticationToken`.
  416. <2> `introspectionRequestConverters()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationConverter``'s allowing the ability to add, remove, or customize a specific `AuthenticationConverter`.
  417. <3> `authenticationProvider()`: Adds an `AuthenticationProvider` (_main processor_) used for authenticating the `OAuth2TokenIntrospectionAuthenticationToken`.
  418. <4> `authenticationProviders()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationProvider``'s allowing the ability to add, remove, or customize a specific `AuthenticationProvider`.
  419. <5> `introspectionResponseHandler()`: The `AuthenticationSuccessHandler` (_post-processor_) used for handling an "`authenticated`" `OAuth2TokenIntrospectionAuthenticationToken` and returning the https://datatracker.ietf.org/doc/html/rfc7662#section-2.2[OAuth2TokenIntrospection response].
  420. <6> `errorResponseHandler()`: The `AuthenticationFailureHandler` (_post-processor_) used for handling an `OAuth2AuthenticationException` and returning the https://datatracker.ietf.org/doc/html/rfc7662#section-2.3[OAuth2Error response].
  421. `OAuth2TokenIntrospectionEndpointConfigurer` configures the `OAuth2TokenIntrospectionEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
  422. `OAuth2TokenIntrospectionEndpointFilter` is the `Filter` that processes OAuth2 introspection requests.
  423. `OAuth2TokenIntrospectionEndpointFilter` is configured with the following defaults:
  424. * `*AuthenticationConverter*` -- An `OAuth2TokenIntrospectionAuthenticationConverter`.
  425. * `*AuthenticationManager*` -- An `AuthenticationManager` composed of `OAuth2TokenIntrospectionAuthenticationProvider`.
  426. * `*AuthenticationSuccessHandler*` -- An internal implementation that handles an "`authenticated`" `OAuth2TokenIntrospectionAuthenticationToken` and returns the `OAuth2TokenIntrospection` response.
  427. * `*AuthenticationFailureHandler*` -- An `OAuth2ErrorAuthenticationFailureHandler`.
  428. [[oauth2-token-revocation-endpoint]]
  429. == OAuth2 Token Revocation Endpoint
  430. `OAuth2TokenRevocationEndpointConfigurer` provides the ability to customize the https://datatracker.ietf.org/doc/html/rfc7009#section-2[OAuth2 Token Revocation endpoint].
  431. It defines extension points that let you customize the pre-processing, main processing, and post-processing logic for https://datatracker.ietf.org/doc/html/rfc7009#section-2.1[OAuth2 revocation requests].
  432. `OAuth2TokenRevocationEndpointConfigurer` provides the following configuration options:
  433. [source,java]
  434. ----
  435. @Bean
  436. public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
  437. OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
  438. OAuth2AuthorizationServerConfigurer.authorizationServer();
  439. http
  440. .securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
  441. .with(authorizationServerConfigurer, (authorizationServer) ->
  442. authorizationServer
  443. .tokenRevocationEndpoint(tokenRevocationEndpoint ->
  444. tokenRevocationEndpoint
  445. .revocationRequestConverter(revocationRequestConverter) <1>
  446. .revocationRequestConverters(revocationRequestConvertersConsumer) <2>
  447. .authenticationProvider(authenticationProvider) <3>
  448. .authenticationProviders(authenticationProvidersConsumer) <4>
  449. .revocationResponseHandler(revocationResponseHandler) <5>
  450. .errorResponseHandler(errorResponseHandler) <6>
  451. )
  452. );
  453. return http.build();
  454. }
  455. ----
  456. <1> `revocationRequestConverter()`: Adds an `AuthenticationConverter` (_pre-processor_) used when attempting to extract an https://datatracker.ietf.org/doc/html/rfc7009#section-2.1[OAuth2 revocation request] from `HttpServletRequest` to an instance of `OAuth2TokenRevocationAuthenticationToken`.
  457. <2> `revocationRequestConverters()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationConverter``'s allowing the ability to add, remove, or customize a specific `AuthenticationConverter`.
  458. <3> `authenticationProvider()`: Adds an `AuthenticationProvider` (_main processor_) used for authenticating the `OAuth2TokenRevocationAuthenticationToken`.
  459. <4> `authenticationProviders()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationProvider``'s allowing the ability to add, remove, or customize a specific `AuthenticationProvider`.
  460. <5> `revocationResponseHandler()`: The `AuthenticationSuccessHandler` (_post-processor_) used for handling an "`authenticated`" `OAuth2TokenRevocationAuthenticationToken` and returning the https://datatracker.ietf.org/doc/html/rfc7009#section-2.2[OAuth2 revocation response].
  461. <6> `errorResponseHandler()`: The `AuthenticationFailureHandler` (_post-processor_) used for handling an `OAuth2AuthenticationException` and returning the https://datatracker.ietf.org/doc/html/rfc7009#section-2.2.1[OAuth2Error response].
  462. `OAuth2TokenRevocationEndpointConfigurer` configures the `OAuth2TokenRevocationEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
  463. `OAuth2TokenRevocationEndpointFilter` is the `Filter` that processes OAuth2 revocation requests.
  464. `OAuth2TokenRevocationEndpointFilter` is configured with the following defaults:
  465. * `*AuthenticationConverter*` -- An `OAuth2TokenRevocationAuthenticationConverter`.
  466. * `*AuthenticationManager*` -- An `AuthenticationManager` composed of `OAuth2TokenRevocationAuthenticationProvider`.
  467. * `*AuthenticationSuccessHandler*` -- An internal implementation that handles an "`authenticated`" `OAuth2TokenRevocationAuthenticationToken` and returns the OAuth2 revocation response.
  468. * `*AuthenticationFailureHandler*` -- An `OAuth2ErrorAuthenticationFailureHandler`.
  469. [[oauth2-authorization-server-metadata-endpoint]]
  470. == OAuth2 Authorization Server Metadata Endpoint
  471. `OAuth2AuthorizationServerMetadataEndpointConfigurer` provides the ability to customize the https://datatracker.ietf.org/doc/html/rfc8414#section-3[OAuth2 Authorization Server Metadata endpoint].
  472. It defines an extension point that lets you customize the https://datatracker.ietf.org/doc/html/rfc8414#section-3.2[OAuth2 Authorization Server Metadata response].
  473. `OAuth2AuthorizationServerMetadataEndpointConfigurer` provides the following configuration option:
  474. [source,java]
  475. ----
  476. @Bean
  477. public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
  478. OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
  479. OAuth2AuthorizationServerConfigurer.authorizationServer();
  480. http
  481. .securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
  482. .with(authorizationServerConfigurer, (authorizationServer) ->
  483. authorizationServer
  484. .authorizationServerMetadataEndpoint(authorizationServerMetadataEndpoint ->
  485. authorizationServerMetadataEndpoint
  486. .authorizationServerMetadataCustomizer(authorizationServerMetadataCustomizer) <1>
  487. )
  488. );
  489. return http.build();
  490. }
  491. ----
  492. <1> `authorizationServerMetadataCustomizer()`: The `Consumer` providing access to the `OAuth2AuthorizationServerMetadata.Builder` allowing the ability to customize the claims of the Authorization Server's configuration.
  493. `OAuth2AuthorizationServerMetadataEndpointConfigurer` configures the `OAuth2AuthorizationServerMetadataEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
  494. `OAuth2AuthorizationServerMetadataEndpointFilter` is the `Filter` that returns the https://datatracker.ietf.org/doc/html/rfc8414#section-3.2[OAuth2AuthorizationServerMetadata response].
  495. [[jwk-set-endpoint]]
  496. == JWK Set Endpoint
  497. `OAuth2AuthorizationServerConfigurer` provides support for the https://datatracker.ietf.org/doc/html/rfc7517[JWK Set endpoint].
  498. `OAuth2AuthorizationServerConfigurer` configures the `NimbusJwkSetEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
  499. `NimbusJwkSetEndpointFilter` is the `Filter` that returns the https://datatracker.ietf.org/doc/html/rfc7517#section-5[JWK Set].
  500. [NOTE]
  501. The JWK Set endpoint is configured *only* if a `JWKSource<SecurityContext>` `@Bean` is registered.
  502. [[oidc-provider-configuration-endpoint]]
  503. == OpenID Connect 1.0 Provider Configuration Endpoint
  504. `OidcProviderConfigurationEndpointConfigurer` provides the ability to customize the https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig[OpenID Connect 1.0 Provider Configuration endpoint].
  505. It defines an extension point that lets you customize the https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse[OpenID Provider Configuration response].
  506. `OidcProviderConfigurationEndpointConfigurer` provides the following configuration option:
  507. [source,java]
  508. ----
  509. @Bean
  510. public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
  511. OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
  512. OAuth2AuthorizationServerConfigurer.authorizationServer();
  513. http
  514. .securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
  515. .with(authorizationServerConfigurer, (authorizationServer) ->
  516. authorizationServer
  517. .oidc(oidc ->
  518. oidc
  519. .providerConfigurationEndpoint(providerConfigurationEndpoint ->
  520. providerConfigurationEndpoint
  521. .providerConfigurationCustomizer(providerConfigurationCustomizer) <1>
  522. )
  523. )
  524. );
  525. return http.build();
  526. }
  527. ----
  528. <1> `providerConfigurationCustomizer()`: The `Consumer` providing access to the `OidcProviderConfiguration.Builder` allowing the ability to customize the claims of the OpenID Provider's configuration.
  529. `OidcProviderConfigurationEndpointConfigurer` configures the `OidcProviderConfigurationEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
  530. `OidcProviderConfigurationEndpointFilter` is the `Filter` that returns the https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse[OidcProviderConfiguration response].
  531. [[oidc-logout-endpoint]]
  532. == OpenID Connect 1.0 Logout Endpoint
  533. `OidcLogoutEndpointConfigurer` provides the ability to customize the https://openid.net/specs/openid-connect-rpinitiated-1_0.html#RPLogout[OpenID Connect 1.0 Logout endpoint].
  534. It defines extension points that let you customize the pre-processing, main processing, and post-processing logic for RP-Initiated Logout requests.
  535. `OidcLogoutEndpointConfigurer` provides the following configuration options:
  536. [source,java]
  537. ----
  538. @Bean
  539. public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
  540. OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
  541. OAuth2AuthorizationServerConfigurer.authorizationServer();
  542. http
  543. .securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
  544. .with(authorizationServerConfigurer, (authorizationServer) ->
  545. authorizationServer
  546. .oidc(oidc ->
  547. oidc
  548. .logoutEndpoint(logoutEndpoint ->
  549. logoutEndpoint
  550. .logoutRequestConverter(logoutRequestConverter) <1>
  551. .logoutRequestConverters(logoutRequestConvertersConsumer) <2>
  552. .authenticationProvider(authenticationProvider) <3>
  553. .authenticationProviders(authenticationProvidersConsumer) <4>
  554. .logoutResponseHandler(logoutResponseHandler) <5>
  555. .errorResponseHandler(errorResponseHandler) <6>
  556. )
  557. )
  558. );
  559. return http.build();
  560. }
  561. ----
  562. <1> `logoutRequestConverter()`: Adds an `AuthenticationConverter` (_pre-processor_) used when attempting to extract a https://openid.net/specs/openid-connect-rpinitiated-1_0.html#RPLogout[Logout request] from `HttpServletRequest` to an instance of `OidcLogoutAuthenticationToken`.
  563. <2> `logoutRequestConverters()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationConverter``'s allowing the ability to add, remove, or customize a specific `AuthenticationConverter`.
  564. <3> `authenticationProvider()`: Adds an `AuthenticationProvider` (_main processor_) used for authenticating the `OidcLogoutAuthenticationToken`.
  565. <4> `authenticationProviders()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationProvider``'s allowing the ability to add, remove, or customize a specific `AuthenticationProvider`.
  566. <5> `logoutResponseHandler()`: The `AuthenticationSuccessHandler` (_post-processor_) used for handling an "`authenticated`" `OidcLogoutAuthenticationToken` and performing the logout.
  567. <6> `errorResponseHandler()`: The `AuthenticationFailureHandler` (_post-processor_) used for handling an `OAuth2AuthenticationException` and returning the error response.
  568. `OidcLogoutEndpointConfigurer` configures the `OidcLogoutEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
  569. `OidcLogoutEndpointFilter` is the `Filter` that processes https://openid.net/specs/openid-connect-rpinitiated-1_0.html#RPLogout[RP-Initiated Logout requests] and performs the logout of the End-User.
  570. `OidcLogoutEndpointFilter` is configured with the following defaults:
  571. * `*AuthenticationConverter*` -- An `OidcLogoutAuthenticationConverter`.
  572. * `*AuthenticationManager*` -- An `AuthenticationManager` composed of `OidcLogoutAuthenticationProvider`.
  573. * `*AuthenticationSuccessHandler*` -- An `OidcLogoutAuthenticationSuccessHandler`.
  574. * `*AuthenticationFailureHandler*` -- An internal implementation that uses the `OAuth2Error` associated with the `OAuth2AuthenticationException` and returns the `OAuth2Error` response.
  575. [NOTE]
  576. `OidcLogoutAuthenticationProvider` uses a xref:core-model-components.adoc#session-registry[`SessionRegistry`] to look up the `SessionInformation` instance associated to the End-User requesting to be logged out.
  577. [TIP]
  578. `OidcClientInitiatedLogoutSuccessHandler` is the corresponding configuration in Spring Security’s OAuth2 Client support for configuring {spring-security-reference-base-url}/servlet/oauth2/login/advanced.html#oauth2login-advanced-oidc-logout[OpenID Connect 1.0 RP-Initiated Logout].
  579. [[oidc-logout-endpoint-customizing-logout-request-validation]]
  580. === Customizing Logout Request Validation
  581. `OidcLogoutAuthenticationValidator` is the default validator used for validating specific OpenID Connect RP-Initiated Logout Request parameters.
  582. The default implementation validates the `post_logout_redirect_uri` parameter.
  583. If validation fails, an `OAuth2AuthenticationException` is thrown.
  584. `OidcLogoutAuthenticationProvider` provides the ability to override the default logout request validation by supplying a custom authentication validator of type `Consumer<OidcLogoutAuthenticationContext>` to `setAuthenticationValidator()`.
  585. [TIP]
  586. `OidcLogoutAuthenticationContext` holds the `OidcLogoutAuthenticationToken`, which contains the logout request parameters.
  587. [IMPORTANT]
  588. If validation fails, the authentication validator *MUST* throw `OAuth2AuthenticationException`.
  589. The following example shows how to configure `OidcLogoutAuthenticationProvider` with a custom authentication validator:
  590. [source,java]
  591. ----
  592. @Bean
  593. public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
  594. OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
  595. OAuth2AuthorizationServerConfigurer.authorizationServer();
  596. http
  597. .securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
  598. .with(authorizationServerConfigurer, (authorizationServer) ->
  599. authorizationServer
  600. .oidc(oidc ->
  601. oidc
  602. .logoutEndpoint(logoutEndpoint ->
  603. logoutEndpoint
  604. .authenticationProviders(configureAuthenticationValidator())
  605. )
  606. )
  607. );
  608. return http.build();
  609. }
  610. private Consumer<List<AuthenticationProvider>> configureAuthenticationValidator() {
  611. return (authenticationProviders) ->
  612. authenticationProviders.forEach((authenticationProvider) -> {
  613. if (authenticationProvider instanceof OidcLogoutAuthenticationProvider oidcLogoutAuthenticationProvider) {
  614. Consumer<OidcLogoutAuthenticationContext> authenticationValidator = new CustomPostLogoutRedirectUriValidator();
  615. oidcLogoutAuthenticationProvider.setAuthenticationValidator(authenticationValidator);
  616. }
  617. });
  618. }
  619. static class CustomPostLogoutRedirectUriValidator implements Consumer<OidcLogoutAuthenticationContext> {
  620. @Override
  621. public void accept(OidcLogoutAuthenticationContext authenticationContext) {
  622. OidcLogoutAuthenticationToken oidcLogoutAuthentication =
  623. authenticationContext.getAuthentication();
  624. RegisteredClient registeredClient = authenticationContext.getRegisteredClient();
  625. // TODO
  626. }
  627. }
  628. ----
  629. [[oidc-user-info-endpoint]]
  630. == OpenID Connect 1.0 UserInfo Endpoint
  631. `OidcUserInfoEndpointConfigurer` provides the ability to customize the https://openid.net/specs/openid-connect-core-1_0.html#UserInfo[OpenID Connect 1.0 UserInfo endpoint].
  632. It defines extension points that let you customize the pre-processing, main processing, and post-processing logic for https://openid.net/specs/openid-connect-core-1_0.html#UserInfoRequest[UserInfo requests].
  633. `OidcUserInfoEndpointConfigurer` provides the following configuration options:
  634. [source,java]
  635. ----
  636. @Bean
  637. public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
  638. OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
  639. OAuth2AuthorizationServerConfigurer.authorizationServer();
  640. http
  641. .securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
  642. .with(authorizationServerConfigurer, (authorizationServer) ->
  643. authorizationServer
  644. .oidc(oidc ->
  645. oidc
  646. .userInfoEndpoint(userInfoEndpoint ->
  647. userInfoEndpoint
  648. .userInfoRequestConverter(userInfoRequestConverter) <1>
  649. .userInfoRequestConverters(userInfoRequestConvertersConsumer) <2>
  650. .authenticationProvider(authenticationProvider) <3>
  651. .authenticationProviders(authenticationProvidersConsumer) <4>
  652. .userInfoResponseHandler(userInfoResponseHandler) <5>
  653. .errorResponseHandler(errorResponseHandler) <6>
  654. .userInfoMapper(userInfoMapper) <7>
  655. )
  656. )
  657. );
  658. return http.build();
  659. }
  660. ----
  661. <1> `userInfoRequestConverter()`: Adds an `AuthenticationConverter` (_pre-processor_) used when attempting to extract an https://openid.net/specs/openid-connect-core-1_0.html#UserInfoRequest[UserInfo request] from `HttpServletRequest` to an instance of `OidcUserInfoAuthenticationToken`.
  662. <2> `userInfoRequestConverters()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationConverter``'s allowing the ability to add, remove, or customize a specific `AuthenticationConverter`.
  663. <3> `authenticationProvider()`: Adds an `AuthenticationProvider` (_main processor_) used for authenticating the `OidcUserInfoAuthenticationToken`.
  664. <4> `authenticationProviders()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationProvider``'s allowing the ability to add, remove, or customize a specific `AuthenticationProvider`.
  665. <5> `userInfoResponseHandler()`: The `AuthenticationSuccessHandler` (_post-processor_) used for handling an "`authenticated`" `OidcUserInfoAuthenticationToken` and returning the https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse[UserInfo response].
  666. <6> `errorResponseHandler()`: The `AuthenticationFailureHandler` (_post-processor_) used for handling an `OAuth2AuthenticationException` and returning the https://openid.net/specs/openid-connect-core-1_0.html#UserInfoError[UserInfo Error response].
  667. <7> `userInfoMapper()`: The `Function` used to extract claims from `OidcUserInfoAuthenticationContext` to an instance of `OidcUserInfo`.
  668. `OidcUserInfoEndpointConfigurer` configures the `OidcUserInfoEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
  669. `OidcUserInfoEndpointFilter` is the `Filter` that processes https://openid.net/specs/openid-connect-core-1_0.html#UserInfoRequest[UserInfo requests] and returns the https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse[OidcUserInfo response].
  670. `OidcUserInfoEndpointFilter` is configured with the following defaults:
  671. * `*AuthenticationConverter*` -- An internal implementation that obtains the `Authentication` from the `SecurityContext` and creates an `OidcUserInfoAuthenticationToken` with the principal.
  672. * `*AuthenticationManager*` -- An `AuthenticationManager` composed of `OidcUserInfoAuthenticationProvider`, which is associated with an internal implementation of `userInfoMapper` that extracts https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims[standard claims] from the https://openid.net/specs/openid-connect-core-1_0.html#IDToken[ID Token] based on the https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims[scopes requested] during authorization.
  673. * `*AuthenticationSuccessHandler*` -- An internal implementation that handles an "`authenticated`" `OidcUserInfoAuthenticationToken` and returns the `OidcUserInfo` response.
  674. * `*AuthenticationFailureHandler*` -- An internal implementation that uses the `OAuth2Error` associated with the `OAuth2AuthenticationException` and returns the `OAuth2Error` response.
  675. [TIP]
  676. You can customize the ID Token by providing an xref:core-model-components.adoc#oauth2-token-customizer[`OAuth2TokenCustomizer<JwtEncodingContext>`] `@Bean`.
  677. The OpenID Connect 1.0 UserInfo endpoint is an OAuth2 protected resource, which *REQUIRES* an access token to be sent as a bearer token in the https://openid.net/specs/openid-connect-core-1_0.html#UserInfoRequest[UserInfo request].
  678. [NOTE]
  679. OAuth2 resource server support is autoconfigured, however, a `JwtDecoder` `@Bean` is *REQUIRED* for the OpenID Connect 1.0 UserInfo endpoint.
  680. [TIP]
  681. The guide xref:guides/how-to-userinfo.adoc[How-to: Customize the OpenID Connect 1.0 UserInfo response] contains examples of customizing the UserInfo endpoint.
  682. [[oidc-client-registration-endpoint]]
  683. == OpenID Connect 1.0 Client Registration Endpoint
  684. `OidcClientRegistrationEndpointConfigurer` provides the ability to customize the https://openid.net/specs/openid-connect-registration-1_0.html#ClientRegistration[OpenID Connect 1.0 Client Registration endpoint].
  685. It defines extension points that let you customize the pre-processing, main processing, and post-processing logic for https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationRequest[Client Registration requests] or https://openid.net/specs/openid-connect-registration-1_0.html#ReadRequest[Client Read requests].
  686. `OidcClientRegistrationEndpointConfigurer` provides the following configuration options:
  687. [source,java]
  688. ----
  689. @Bean
  690. public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
  691. OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
  692. OAuth2AuthorizationServerConfigurer.authorizationServer();
  693. http
  694. .securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
  695. .with(authorizationServerConfigurer, (authorizationServer) ->
  696. authorizationServer
  697. .oidc(oidc ->
  698. oidc
  699. .clientRegistrationEndpoint(clientRegistrationEndpoint ->
  700. clientRegistrationEndpoint
  701. .clientRegistrationRequestConverter(clientRegistrationRequestConverter) <1>
  702. .clientRegistrationRequestConverters(clientRegistrationRequestConvertersConsumers) <2>
  703. .authenticationProvider(authenticationProvider) <3>
  704. .authenticationProviders(authenticationProvidersConsumer) <4>
  705. .clientRegistrationResponseHandler(clientRegistrationResponseHandler) <5>
  706. .errorResponseHandler(errorResponseHandler) <6>
  707. )
  708. )
  709. );
  710. return http.build();
  711. }
  712. ----
  713. <1> `clientRegistrationRequestConverter()`: Adds an `AuthenticationConverter` (_pre-processor_) used when attempting to extract a https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationRequest[Client Registration request] or https://openid.net/specs/openid-connect-registration-1_0.html#ReadRequest[Client Read request] from `HttpServletRequest` to an instance of `OidcClientRegistrationAuthenticationToken`.
  714. <2> `clientRegistrationRequestConverters()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationConverter``'s allowing the ability to add, remove, or customize a specific `AuthenticationConverter`.
  715. <3> `authenticationProvider()`: Adds an `AuthenticationProvider` (_main processor_) used for authenticating the `OidcClientRegistrationAuthenticationToken`.
  716. <4> `authenticationProviders()`: Sets the `Consumer` providing access to the `List` of default and (optionally) added ``AuthenticationProvider``'s allowing the ability to add, remove, or customize a specific `AuthenticationProvider`.
  717. <5> `clientRegistrationResponseHandler()`: The `AuthenticationSuccessHandler` (_post-processor_) used for handling an "`authenticated`" `OidcClientRegistrationAuthenticationToken` and returning the https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationResponse[Client Registration response] or https://openid.net/specs/openid-connect-registration-1_0.html#ReadResponse[Client Read response].
  718. <6> `errorResponseHandler()`: The `AuthenticationFailureHandler` (_post-processor_) used for handling an `OAuth2AuthenticationException` and returning the https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationError[Client Registration Error response] or https://openid.net/specs/openid-connect-registration-1_0.html#ReadError[Client Read Error response].
  719. [NOTE]
  720. The OpenID Connect 1.0 Client Registration endpoint is disabled by default because many deployments do not require dynamic client registration.
  721. `OidcClientRegistrationEndpointConfigurer` configures the `OidcClientRegistrationEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
  722. `OidcClientRegistrationEndpointFilter` is the `Filter` that processes https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationRequest[Client Registration requests] and returns the https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationResponse[OidcClientRegistration response].
  723. [TIP]
  724. `OidcClientRegistrationEndpointFilter` also processes https://openid.net/specs/openid-connect-registration-1_0.html#ReadRequest[Client Read requests] and returns the https://openid.net/specs/openid-connect-registration-1_0.html#ReadResponse[OidcClientRegistration response].
  725. `OidcClientRegistrationEndpointFilter` is configured with the following defaults:
  726. * `*AuthenticationConverter*` -- An `OidcClientRegistrationAuthenticationConverter`.
  727. * `*AuthenticationManager*` -- An `AuthenticationManager` composed of `OidcClientRegistrationAuthenticationProvider` and `OidcClientConfigurationAuthenticationProvider`.
  728. * `*AuthenticationSuccessHandler*` -- An internal implementation that handles an "`authenticated`" `OidcClientRegistrationAuthenticationToken` and returns the `OidcClientRegistration` response.
  729. * `*AuthenticationFailureHandler*` -- An internal implementation that uses the `OAuth2Error` associated with the `OAuth2AuthenticationException` and returns the `OAuth2Error` response.
  730. The OpenID Connect 1.0 Client Registration endpoint is an https://openid.net/specs/openid-connect-registration-1_0.html#ClientRegistration[OAuth2 protected resource], which *REQUIRES* an access token to be sent as a bearer token in the Client Registration (or Client Read) request.
  731. [NOTE]
  732. OAuth2 resource server support is autoconfigured, however, a `JwtDecoder` `@Bean` is *REQUIRED* for the OpenID Connect 1.0 Client Registration endpoint.
  733. [IMPORTANT]
  734. The access token in a Client Registration request *REQUIRES* the OAuth2 scope `client.create`.
  735. [IMPORTANT]
  736. The access token in a Client Read request *REQUIRES* the OAuth2 scope `client.read`.