From 5da0cbea4be0f11f1c4f12fb4476f1ab00635eb9 Mon Sep 17 00:00:00 2001 From: Joe Grandja <10884212+jgrandja@users.noreply.github.com> Date: Thu, 30 Oct 2025 12:58:05 -0400 Subject: [PATCH] Document OAuth 2.0 Dynamic Client Registration support Issue gh-17964 --- .../configuration-model.adoc | 29 +++++---- .../oauth2/authorization-server/index.adoc | 2 + .../protocol-endpoints.adoc | 62 ++++++++++++++++++- 3 files changed, 81 insertions(+), 12 deletions(-) diff --git a/docs/modules/ROOT/pages/servlet/oauth2/authorization-server/configuration-model.adoc b/docs/modules/ROOT/pages/servlet/oauth2/authorization-server/configuration-model.adoc index eb65445664..06a62990d3 100644 --- a/docs/modules/ROOT/pages/servlet/oauth2/authorization-server/configuration-model.adoc +++ b/docs/modules/ROOT/pages/servlet/oauth2/authorization-server/configuration-model.adoc @@ -22,6 +22,9 @@ The OAuth2 authorization server `SecurityFilterChain` `@Bean` is configured with [NOTE] The JWK Set endpoint is configured *only* if a `JWKSource` `@Bean` is registered. +[NOTE] +The xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-oauth2-client-registration-endpoint[OAuth2 Client Registration endpoint] is disabled by default. + The following example shows how to use `OAuth2AuthorizationServerConfiguration` to apply the minimal default configuration: [source,java] @@ -71,7 +74,7 @@ In addition to the default protocol endpoints, the OAuth2 authorization server ` * xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-oidc-user-info-endpoint[OpenID Connect 1.0 UserInfo endpoint] [NOTE] -The xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-oidc-client-registration-endpoint[OpenID Connect 1.0 Client Registration endpoint] is disabled by default because many deployments do not require dynamic client registration. +The xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-oidc-client-registration-endpoint[OpenID Connect 1.0 Client Registration endpoint] is disabled by default. [TIP] `OAuth2AuthorizationServerConfiguration.jwtDecoder(JWKSource)` is a convenience (`static`) utility method that can be used to register a `JwtDecoder` `@Bean`, which is *REQUIRED* for the xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-oidc-user-info-endpoint[OpenID Connect 1.0 UserInfo endpoint] and the xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-oidc-client-registration-endpoint[OpenID Connect 1.0 Client Registration endpoint]. @@ -117,12 +120,13 @@ public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity h .tokenEndpoint(tokenEndpoint -> { }) <11> .tokenIntrospectionEndpoint(tokenIntrospectionEndpoint -> { }) <12> .tokenRevocationEndpoint(tokenRevocationEndpoint -> { }) <13> - .authorizationServerMetadataEndpoint(authorizationServerMetadataEndpoint -> { }) <14> + .clientRegistrationEndpoint(clientRegistrationEndpoint -> { }) <14> + .authorizationServerMetadataEndpoint(authorizationServerMetadataEndpoint -> { }) <15> .oidc(oidc -> oidc - .providerConfigurationEndpoint(providerConfigurationEndpoint -> { }) <15> - .logoutEndpoint(logoutEndpoint -> { }) <16> - .userInfoEndpoint(userInfoEndpoint -> { }) <17> - .clientRegistrationEndpoint(clientRegistrationEndpoint -> { }) <18> + .providerConfigurationEndpoint(providerConfigurationEndpoint -> { }) <16> + .logoutEndpoint(logoutEndpoint -> { }) <17> + .userInfoEndpoint(userInfoEndpoint -> { }) <18> + .clientRegistrationEndpoint(clientRegistrationEndpoint -> { }) <19> ) ); @@ -142,11 +146,12 @@ public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity h <11> `tokenEndpoint()`: The configurer for the xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-oauth2-token-endpoint[OAuth2 Token endpoint]. <12> `tokenIntrospectionEndpoint()`: The configurer for the xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-oauth2-token-introspection-endpoint[OAuth2 Token Introspection endpoint]. <13> `tokenRevocationEndpoint()`: The configurer for the xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-oauth2-token-revocation-endpoint[OAuth2 Token Revocation endpoint]. -<14> `authorizationServerMetadataEndpoint()`: The configurer for the xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-oauth2-authorization-server-metadata-endpoint[OAuth2 Authorization Server Metadata endpoint]. -<15> `providerConfigurationEndpoint()`: The configurer for the xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-oidc-provider-configuration-endpoint[OpenID Connect 1.0 Provider Configuration endpoint]. -<16> `logoutEndpoint()`: The configurer for the xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-oidc-logout-endpoint[OpenID Connect 1.0 Logout endpoint]. -<17> `userInfoEndpoint()`: The configurer for the xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-oidc-user-info-endpoint[OpenID Connect 1.0 UserInfo endpoint]. -<18> `clientRegistrationEndpoint()`: The configurer for the xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-oidc-client-registration-endpoint[OpenID Connect 1.0 Client Registration endpoint]. +<14> `clientRegistrationEndpoint()`: The configurer for the xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-oauth2-client-registration-endpoint[OAuth2 Client Registration endpoint]. +<15> `authorizationServerMetadataEndpoint()`: The configurer for the xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-oauth2-authorization-server-metadata-endpoint[OAuth2 Authorization Server Metadata endpoint]. +<16> `providerConfigurationEndpoint()`: The configurer for the xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-oidc-provider-configuration-endpoint[OpenID Connect 1.0 Provider Configuration endpoint]. +<17> `logoutEndpoint()`: The configurer for the xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-oidc-logout-endpoint[OpenID Connect 1.0 Logout endpoint]. +<18> `userInfoEndpoint()`: The configurer for the xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-oidc-user-info-endpoint[OpenID Connect 1.0 UserInfo endpoint]. +<19> `clientRegistrationEndpoint()`: The configurer for the xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-oidc-client-registration-endpoint[OpenID Connect 1.0 Client Registration endpoint]. [[oauth2AuthorizationServer-configuring-authorization-server-settings]] == Configuring Authorization Server Settings @@ -170,6 +175,7 @@ public final class AuthorizationServerSettings extends AbstractSettings { .tokenEndpoint("/oauth2/token") .tokenIntrospectionEndpoint("/oauth2/introspect") .tokenRevocationEndpoint("/oauth2/revoke") + .clientRegistrationEndpoint("/oauth2/register") .jwkSetEndpoint("/oauth2/jwks") .oidcLogoutEndpoint("/connect/logout") .oidcUserInfoEndpoint("/userinfo") @@ -202,6 +208,7 @@ public AuthorizationServerSettings authorizationServerSettings() { .tokenEndpoint("/oauth2/v1/token") .tokenIntrospectionEndpoint("/oauth2/v1/introspect") .tokenRevocationEndpoint("/oauth2/v1/revoke") + .clientRegistrationEndpoint("/oauth2/v1/register") .jwkSetEndpoint("/oauth2/v1/jwks") .oidcLogoutEndpoint("/connect/v1/logout") .oidcUserInfoEndpoint("/connect/v1/userinfo") diff --git a/docs/modules/ROOT/pages/servlet/oauth2/authorization-server/index.adoc b/docs/modules/ROOT/pages/servlet/oauth2/authorization-server/index.adoc index 7940fa763d..a228ca6b7b 100644 --- a/docs/modules/ROOT/pages/servlet/oauth2/authorization-server/index.adoc +++ b/docs/modules/ROOT/pages/servlet/oauth2/authorization-server/index.adoc @@ -86,6 +86,7 @@ Spring Security Authorization Server supports the following features: * xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-oauth2-token-endpoint[OAuth2 Token Endpoint] * xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-oauth2-token-introspection-endpoint[OAuth2 Token Introspection Endpoint] * xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-oauth2-token-revocation-endpoint[OAuth2 Token Revocation Endpoint] +* xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-oauth2-client-registration-endpoint[OAuth2 Client Registration Endpoint] * xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-oauth2-authorization-server-metadata-endpoint[OAuth2 Authorization Server Metadata Endpoint] * xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-jwk-set-endpoint[JWK Set Endpoint] * xref:servlet/oauth2/authorization-server/protocol-endpoints.adoc#oauth2AuthorizationServer-oidc-provider-configuration-endpoint[OpenID Connect 1.0 Provider Configuration Endpoint] @@ -103,6 +104,7 @@ Spring Security Authorization Server supports the following features: ** https://tools.ietf.org/html/rfc8628#section-3.3[Device Verification Endpoint] * OAuth 2.0 Token Introspection (https://tools.ietf.org/html/rfc7662[RFC 7662]) * OAuth 2.0 Token Revocation (https://tools.ietf.org/html/rfc7009[RFC 7009]) +* OAuth 2.0 Dynamic Client Registration Protocol (https://datatracker.ietf.org/doc/html/rfc7591[RFC 7591]) * OAuth 2.0 Authorization Server Metadata (https://tools.ietf.org/html/rfc8414[RFC 8414]) * JSON Web Key (JWK) (https://tools.ietf.org/html/rfc7517[RFC 7517]) * OpenID Connect Discovery 1.0 (https://openid.net/specs/openid-connect-discovery-1_0.html[spec]) diff --git a/docs/modules/ROOT/pages/servlet/oauth2/authorization-server/protocol-endpoints.adoc b/docs/modules/ROOT/pages/servlet/oauth2/authorization-server/protocol-endpoints.adoc index 82919e4ff6..b62621f30d 100644 --- a/docs/modules/ROOT/pages/servlet/oauth2/authorization-server/protocol-endpoints.adoc +++ b/docs/modules/ROOT/pages/servlet/oauth2/authorization-server/protocol-endpoints.adoc @@ -664,6 +664,66 @@ public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity h * `*AuthenticationSuccessHandler*` -- An internal implementation that handles an "`authenticated`" `OAuth2TokenRevocationAuthenticationToken` and returns the OAuth2 revocation response. * `*AuthenticationFailureHandler*` -- An `OAuth2ErrorAuthenticationFailureHandler`. +[[oauth2AuthorizationServer-oauth2-client-registration-endpoint]] +== OAuth2 Client Registration Endpoint + +`OAuth2ClientRegistrationEndpointConfigurer` provides the ability to customize the https://datatracker.ietf.org/doc/html/rfc7591#section-3[OAuth2 Client Registration endpoint]. +It defines extension points that let you customize the pre-processing, main processing, and post-processing logic for https://datatracker.ietf.org/doc/html/rfc7591#section-3.1[Client Registration requests]. + +`OAuth2ClientRegistrationEndpointConfigurer` provides the following configuration options: + +[source,java] +---- +@Bean +public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception { + http + .oauth2AuthorizationServer((authorizationServer) -> + authorizationServer + .clientRegistrationEndpoint(clientRegistrationEndpoint -> + clientRegistrationEndpoint + .clientRegistrationRequestConverter(clientRegistrationRequestConverter) <1> + .clientRegistrationRequestConverters(clientRegistrationRequestConvertersConsumer) <2> + .authenticationProvider(authenticationProvider) <3> + .authenticationProviders(authenticationProvidersConsumer) <4> + .clientRegistrationResponseHandler(clientRegistrationResponseHandler) <5> + .errorResponseHandler(errorResponseHandler) <6> + ) + ); + + return http.build(); +} +---- +<1> `clientRegistrationRequestConverter()`: Adds an `AuthenticationConverter` (_pre-processor_) used when attempting to extract a https://datatracker.ietf.org/doc/html/rfc7591#section-3.1[Client Registration request] from `HttpServletRequest` to an instance of `OAuth2ClientRegistrationAuthenticationToken`. +<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`. +<3> `authenticationProvider()`: Adds an `AuthenticationProvider` (_main processor_) used for authenticating the `OAuth2ClientRegistrationAuthenticationToken`. +<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`. +<5> `clientRegistrationResponseHandler()`: The `AuthenticationSuccessHandler` (_post-processor_) used for handling an "`authenticated`" `OAuth2ClientRegistrationAuthenticationToken` and returning the https://datatracker.ietf.org/doc/html/rfc7591#section-3.2.1[Client Registration response]. +<6> `errorResponseHandler()`: The `AuthenticationFailureHandler` (_post-processor_) used for handling an `OAuth2AuthenticationException` and returning the https://datatracker.ietf.org/doc/html/rfc7591#section-3.2.2[Client Registration Error response]. + +[NOTE] +The OAuth2 Client Registration endpoint is disabled by default. + +`OAuth2ClientRegistrationEndpointConfigurer` configures the `OAuth2ClientRegistrationEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`. +`OAuth2ClientRegistrationEndpointFilter` is the `Filter` that processes https://datatracker.ietf.org/doc/html/rfc7591#section-3.1[Client Registration requests] and returns the https://datatracker.ietf.org/doc/html/rfc7591#section-3.2.1[OAuth2ClientRegistration response]. + +`OAuth2ClientRegistrationEndpointFilter` is configured with the following defaults: + +* `*AuthenticationConverter*` -- An `OAuth2ClientRegistrationAuthenticationConverter`. +* `*AuthenticationManager*` -- An `AuthenticationManager` composed of `OAuth2ClientRegistrationAuthenticationProvider`. +* `*AuthenticationSuccessHandler*` -- An internal implementation that handles an "`authenticated`" `OAuth2ClientRegistrationAuthenticationToken` and returns the `OAuth2ClientRegistration` response. +* `*AuthenticationFailureHandler*` -- An internal implementation that uses the `OAuth2Error` associated with the `OAuth2AuthenticationException` and returns the `OAuth2Error` response. + +The OAuth2 Client Registration endpoint is an https://datatracker.ietf.org/doc/html/rfc7591#section-3[OAuth2 protected resource], which *REQUIRES* an access token to be sent as a bearer token in the Client Registration request. + +[NOTE] +OAuth2 resource server support is autoconfigured, however, a `JwtDecoder` `@Bean` is *REQUIRED* for the OAuth2 Client Registration endpoint. + +[IMPORTANT] +The access token in a Client Registration request *REQUIRES* the OAuth2 scope `client.create`. + +[TIP] +To allow open client registration (no access token in request), configure `OAuth2ClientRegistrationAuthenticationProvider.setOpenRegistrationAllowed(true)`. + [[oauth2AuthorizationServer-oauth2-authorization-server-metadata-endpoint]] == OAuth2 Authorization Server Metadata Endpoint @@ -950,7 +1010,7 @@ public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity h <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]. [NOTE] -The OpenID Connect 1.0 Client Registration endpoint is disabled by default because many deployments do not require dynamic client registration. +The OpenID Connect 1.0 Client Registration endpoint is disabled by default. `OidcClientRegistrationEndpointConfigurer` configures the `OidcClientRegistrationEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`. `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].