[[configuration-model]] = Configuration Model [[default-configuration]] == Default configuration `OAuth2AuthorizationServerConfiguration` is a `@Configuration` that provides the minimal default configuration for an OAuth2 authorization server. `OAuth2AuthorizationServerConfiguration` uses xref:configuration-model.adoc#customizing-the-configuration[`OAuth2AuthorizationServerConfigurer`] to apply the default configuration and registers a `SecurityFilterChain` `@Bean` composed of all the infrastructure components supporting an OAuth2 authorization server. The OAuth2 authorization server `SecurityFilterChain` `@Bean` is configured with the following default protocol endpoints: * xref:protocol-endpoints.adoc#oauth2-authorization-endpoint[OAuth2 Authorization endpoint] * xref:protocol-endpoints.adoc#oauth2-device-authorization-endpoint[OAuth2 Device Authorization Endpoint] * xref:protocol-endpoints.adoc#oauth2-device-verification-endpoint[OAuth2 Device Verification Endpoint] * xref:protocol-endpoints.adoc#oauth2-token-endpoint[OAuth2 Token endpoint] * xref:protocol-endpoints.adoc#oauth2-token-introspection-endpoint[OAuth2 Token Introspection endpoint] * xref:protocol-endpoints.adoc#oauth2-token-revocation-endpoint[OAuth2 Token Revocation endpoint] * xref:protocol-endpoints.adoc#oauth2-authorization-server-metadata-endpoint[OAuth2 Authorization Server Metadata endpoint] * xref:protocol-endpoints.adoc#jwk-set-endpoint[JWK Set endpoint] [NOTE] The JWK Set endpoint is configured *only* if a `JWKSource` `@Bean` is registered. The following example shows how to use `OAuth2AuthorizationServerConfiguration` to apply the minimal default configuration: [source,java] ---- @Configuration @Import(OAuth2AuthorizationServerConfiguration.class) public class AuthorizationServerConfig { @Bean public RegisteredClientRepository registeredClientRepository() { List registrations = ... return new InMemoryRegisteredClientRepository(registrations); } @Bean public JWKSource jwkSource() { RSAKey rsaKey = ... JWKSet jwkSet = new JWKSet(rsaKey); return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet); } } ---- [IMPORTANT] The https://datatracker.ietf.org/doc/html/rfc6749#section-4.1[authorization_code grant] requires the resource owner to be authenticated. Therefore, a user authentication mechanism *must* be configured in addition to the default OAuth2 security configuration. https://openid.net/specs/openid-connect-core-1_0.html[OpenID Connect 1.0] is disabled in the default configuration. The following example shows how to enable OpenID Connect 1.0 by initializing the `OidcConfigurer`: [source,java] ---- @Bean public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception { OAuth2AuthorizationServerConfigurer authorizationServerConfigurer = OAuth2AuthorizationServerConfigurer.authorizationServer(); http .securityMatcher(authorizationServerConfigurer.getEndpointsMatcher()) .with(authorizationServerConfigurer, (authorizationServer) -> authorizationServer .oidc(Customizer.withDefaults()) // Initialize `OidcConfigurer` ); return http.build(); } ---- In addition to the default protocol endpoints, the OAuth2 authorization server `SecurityFilterChain` `@Bean` is configured with the following OpenID Connect 1.0 protocol endpoints: * xref:protocol-endpoints.adoc#oidc-provider-configuration-endpoint[OpenID Connect 1.0 Provider Configuration endpoint] * xref:protocol-endpoints.adoc#oidc-logout-endpoint[OpenID Connect 1.0 Logout endpoint] * xref:protocol-endpoints.adoc#oidc-user-info-endpoint[OpenID Connect 1.0 UserInfo endpoint] [NOTE] The xref:protocol-endpoints.adoc#oidc-client-registration-endpoint[OpenID Connect 1.0 Client Registration endpoint] is disabled by default because many deployments do not require dynamic client registration. [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:protocol-endpoints.adoc#oidc-user-info-endpoint[OpenID Connect 1.0 UserInfo endpoint] and the xref:protocol-endpoints.adoc#oidc-client-registration-endpoint[OpenID Connect 1.0 Client Registration endpoint]. The following example shows how to register a `JwtDecoder` `@Bean`: [source,java] ---- @Bean public JwtDecoder jwtDecoder(JWKSource jwkSource) { return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource); } ---- The main intent of `OAuth2AuthorizationServerConfiguration` is to provide a convenient method to apply the minimal default configuration for an OAuth2 authorization server. However, in most cases, customizing the configuration will be required. [[customizing-the-configuration]] == Customizing the configuration `OAuth2AuthorizationServerConfigurer` provides the ability to fully customize the security configuration for an OAuth2 authorization server. It lets you specify the core components to use - for example, xref:core-model-components.adoc#registered-client-repository[`RegisteredClientRepository`], xref:core-model-components.adoc#oauth2-authorization-service[`OAuth2AuthorizationService`], xref:core-model-components.adoc#oauth2-token-generator[`OAuth2TokenGenerator`], and others. Furthermore, it lets you customize the request processing logic for the protocol endpoints – for example, xref:protocol-endpoints.adoc#oauth2-authorization-endpoint[authorization endpoint], xref:protocol-endpoints.adoc#oauth2-device-authorization-endpoint[device authorization endpoint], xref:protocol-endpoints.adoc#oauth2-device-verification-endpoint[device verification endpoint], xref:protocol-endpoints.adoc#oauth2-token-endpoint[token endpoint], xref:protocol-endpoints.adoc#oauth2-token-introspection-endpoint[token introspection endpoint], and others. `OAuth2AuthorizationServerConfigurer` provides the following configuration options: [source,java] ---- @Bean public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception { OAuth2AuthorizationServerConfigurer authorizationServerConfigurer = OAuth2AuthorizationServerConfigurer.authorizationServer(); http .securityMatcher(authorizationServerConfigurer.getEndpointsMatcher()) .with(authorizationServerConfigurer, (authorizationServer) -> authorizationServer .registeredClientRepository(registeredClientRepository) <1> .authorizationService(authorizationService) <2> .authorizationConsentService(authorizationConsentService) <3> .authorizationServerSettings(authorizationServerSettings) <4> .tokenGenerator(tokenGenerator) <5> .clientAuthentication(clientAuthentication -> { }) <6> .authorizationEndpoint(authorizationEndpoint -> { }) <7> .pushedAuthorizationRequestEndpoint(pushedAuthorizationRequestEndpoint -> { }) <8> .deviceAuthorizationEndpoint(deviceAuthorizationEndpoint -> { }) <9> .deviceVerificationEndpoint(deviceVerificationEndpoint -> { }) <10> .tokenEndpoint(tokenEndpoint -> { }) <11> .tokenIntrospectionEndpoint(tokenIntrospectionEndpoint -> { }) <12> .tokenRevocationEndpoint(tokenRevocationEndpoint -> { }) <13> .authorizationServerMetadataEndpoint(authorizationServerMetadataEndpoint -> { }) <14> .oidc(oidc -> oidc .providerConfigurationEndpoint(providerConfigurationEndpoint -> { }) <15> .logoutEndpoint(logoutEndpoint -> { }) <16> .userInfoEndpoint(userInfoEndpoint -> { }) <17> .clientRegistrationEndpoint(clientRegistrationEndpoint -> { }) <18> ) ); return http.build(); } ---- <1> `registeredClientRepository()`: The xref:core-model-components.adoc#registered-client-repository[`RegisteredClientRepository`] (*REQUIRED*) for managing new and existing clients. <2> `authorizationService()`: The xref:core-model-components.adoc#oauth2-authorization-service[`OAuth2AuthorizationService`] for managing new and existing authorizations. <3> `authorizationConsentService()`: The xref:core-model-components.adoc#oauth2-authorization-consent-service[`OAuth2AuthorizationConsentService`] for managing new and existing authorization consents. <4> `authorizationServerSettings()`: The xref:configuration-model.adoc#configuring-authorization-server-settings[`AuthorizationServerSettings`] (*REQUIRED*) for customizing configuration settings for the OAuth2 authorization server. <5> `tokenGenerator()`: The xref:core-model-components.adoc#oauth2-token-generator[`OAuth2TokenGenerator`] for generating tokens supported by the OAuth2 authorization server. <6> `clientAuthentication()`: The configurer for xref:configuration-model.adoc#configuring-client-authentication[OAuth2 Client Authentication]. <7> `authorizationEndpoint()`: The configurer for the xref:protocol-endpoints.adoc#oauth2-authorization-endpoint[OAuth2 Authorization endpoint]. <8> `pushedAuthorizationRequestEndpoint()`: The configurer for the xref:protocol-endpoints.adoc#oauth2-pushed-authorization-request-endpoint[OAuth2 Pushed Authorization Request endpoint]. <9> `deviceAuthorizationEndpoint()`: The configurer for the xref:protocol-endpoints.adoc#oauth2-device-authorization-endpoint[OAuth2 Device Authorization endpoint]. <10> `deviceVerificationEndpoint()`: The configurer for the xref:protocol-endpoints.adoc#oauth2-device-verification-endpoint[OAuth2 Device Verification endpoint]. <11> `tokenEndpoint()`: The configurer for the xref:protocol-endpoints.adoc#oauth2-token-endpoint[OAuth2 Token endpoint]. <12> `tokenIntrospectionEndpoint()`: The configurer for the xref:protocol-endpoints.adoc#oauth2-token-introspection-endpoint[OAuth2 Token Introspection endpoint]. <13> `tokenRevocationEndpoint()`: The configurer for the xref:protocol-endpoints.adoc#oauth2-token-revocation-endpoint[OAuth2 Token Revocation endpoint]. <14> `authorizationServerMetadataEndpoint()`: The configurer for the xref:protocol-endpoints.adoc#oauth2-authorization-server-metadata-endpoint[OAuth2 Authorization Server Metadata endpoint]. <15> `providerConfigurationEndpoint()`: The configurer for the xref:protocol-endpoints.adoc#oidc-provider-configuration-endpoint[OpenID Connect 1.0 Provider Configuration endpoint]. <16> `logoutEndpoint()`: The configurer for the xref:protocol-endpoints.adoc#oidc-logout-endpoint[OpenID Connect 1.0 Logout endpoint]. <17> `userInfoEndpoint()`: The configurer for the xref:protocol-endpoints.adoc#oidc-user-info-endpoint[OpenID Connect 1.0 UserInfo endpoint]. <18> `clientRegistrationEndpoint()`: The configurer for the xref:protocol-endpoints.adoc#oidc-client-registration-endpoint[OpenID Connect 1.0 Client Registration endpoint]. [[configuring-authorization-server-settings]] == Configuring Authorization Server Settings `AuthorizationServerSettings` contains the configuration settings for the OAuth2 authorization server. It specifies the `URI` for the protocol endpoints as well as the https://datatracker.ietf.org/doc/html/rfc8414#section-2[issuer identifier]. The default `URI` for the protocol endpoints are as follows: [source,java] ---- public final class AuthorizationServerSettings extends AbstractSettings { ... public static Builder builder() { return new Builder() .authorizationEndpoint("/oauth2/authorize") .pushedAuthorizationRequestEndpoint("/oauth2/par") .deviceAuthorizationEndpoint("/oauth2/device_authorization") .deviceVerificationEndpoint("/oauth2/device_verification") .tokenEndpoint("/oauth2/token") .tokenIntrospectionEndpoint("/oauth2/introspect") .tokenRevocationEndpoint("/oauth2/revoke") .jwkSetEndpoint("/oauth2/jwks") .oidcLogoutEndpoint("/connect/logout") .oidcUserInfoEndpoint("/userinfo") .oidcClientRegistrationEndpoint("/connect/register"); } ... } ---- [NOTE] `AuthorizationServerSettings` is a *REQUIRED* component. [TIP] xref:configuration-model.adoc#default-configuration[`@Import(OAuth2AuthorizationServerConfiguration.class)`] automatically registers an `AuthorizationServerSettings` `@Bean`, if not already provided. The following example shows how to customize the configuration settings and register an `AuthorizationServerSettings` `@Bean`: [source,java] ---- @Bean public AuthorizationServerSettings authorizationServerSettings() { return AuthorizationServerSettings.builder() .issuer("https://example.com") .authorizationEndpoint("/oauth2/v1/authorize") .pushedAuthorizationRequestEndpoint("/oauth2/v1/par") .deviceAuthorizationEndpoint("/oauth2/v1/device_authorization") .deviceVerificationEndpoint("/oauth2/v1/device_verification") .tokenEndpoint("/oauth2/v1/token") .tokenIntrospectionEndpoint("/oauth2/v1/introspect") .tokenRevocationEndpoint("/oauth2/v1/revoke") .jwkSetEndpoint("/oauth2/v1/jwks") .oidcLogoutEndpoint("/connect/v1/logout") .oidcUserInfoEndpoint("/connect/v1/userinfo") .oidcClientRegistrationEndpoint("/connect/v1/register") .build(); } ---- The `AuthorizationServerContext` is a context object that holds information of the Authorization Server runtime environment. It provides access to the `AuthorizationServerSettings` and the "`current`" issuer identifier. [NOTE] If the issuer identifier is not configured in `AuthorizationServerSettings.builder().issuer(String)`, it is resolved from the current request. [NOTE] The `AuthorizationServerContext` is accessible through the `AuthorizationServerContextHolder`, which associates it with the current request thread by using a `ThreadLocal`. [[configuring-client-authentication]] == Configuring Client Authentication `OAuth2ClientAuthenticationConfigurer` provides the ability to customize https://datatracker.ietf.org/doc/html/rfc6749#section-2.3[OAuth2 client authentication]. It defines extension points that let you customize the pre-processing, main processing, and post-processing logic for client authentication requests. `OAuth2ClientAuthenticationConfigurer` provides the following configuration options: [source,java] ---- @Bean public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception { OAuth2AuthorizationServerConfigurer authorizationServerConfigurer = OAuth2AuthorizationServerConfigurer.authorizationServer(); http .securityMatcher(authorizationServerConfigurer.getEndpointsMatcher()) .with(authorizationServerConfigurer, (authorizationServer) -> authorizationServer .clientAuthentication(clientAuthentication -> clientAuthentication .authenticationConverter(authenticationConverter) <1> .authenticationConverters(authenticationConvertersConsumer) <2> .authenticationProvider(authenticationProvider) <3> .authenticationProviders(authenticationProvidersConsumer) <4> .authenticationSuccessHandler(authenticationSuccessHandler) <5> .errorResponseHandler(errorResponseHandler) <6> ) ); return http.build(); } ---- <1> `authenticationConverter()`: Adds an `AuthenticationConverter` (_pre-processor_) used when attempting to extract client credentials from `HttpServletRequest` to an instance of `OAuth2ClientAuthenticationToken`. <2> `authenticationConverters()`: 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 `OAuth2ClientAuthenticationToken`. <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> `authenticationSuccessHandler()`: The `AuthenticationSuccessHandler` (_post-processor_) used for handling a successful client authentication and associating the `OAuth2ClientAuthenticationToken` to the `SecurityContext`. <6> `errorResponseHandler()`: The `AuthenticationFailureHandler` (_post-processor_) used for handling a failed client authentication and returning the https://datatracker.ietf.org/doc/html/rfc6749#section-5.2[`OAuth2Error` response]. `OAuth2ClientAuthenticationConfigurer` configures the `OAuth2ClientAuthenticationFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`. `OAuth2ClientAuthenticationFilter` is the `Filter` that processes client authentication requests. By default, client authentication is required for the xref:protocol-endpoints.adoc#oauth2-token-endpoint[OAuth2 Token endpoint], the xref:protocol-endpoints.adoc#oauth2-token-introspection-endpoint[OAuth2 Token Introspection endpoint], and the xref:protocol-endpoints.adoc#oauth2-token-revocation-endpoint[OAuth2 Token Revocation endpoint]. The supported client authentication methods are `client_secret_basic`, `client_secret_post`, `private_key_jwt`, `client_secret_jwt`, `tls_client_auth`, `self_signed_tls_client_auth`, and `none` (public clients). `OAuth2ClientAuthenticationFilter` is configured with the following defaults: * `*AuthenticationConverter*` -- A `DelegatingAuthenticationConverter` composed of `JwtClientAssertionAuthenticationConverter`, `X509ClientCertificateAuthenticationConverter`, `ClientSecretBasicAuthenticationConverter`, `ClientSecretPostAuthenticationConverter`, and `PublicClientAuthenticationConverter`. * `*AuthenticationManager*` -- An `AuthenticationManager` composed of `JwtClientAssertionAuthenticationProvider`, `X509ClientCertificateAuthenticationProvider`, `ClientSecretAuthenticationProvider`, and `PublicClientAuthenticationProvider`. * `*AuthenticationSuccessHandler*` -- An internal implementation that associates the "`authenticated`" `OAuth2ClientAuthenticationToken` (current `Authentication`) to the `SecurityContext`. * `*AuthenticationFailureHandler*` -- An internal implementation that uses the `OAuth2Error` associated with the `OAuth2AuthenticationException` to return the OAuth2 error response. [[configuring-client-authentication-customizing-jwt-client-assertion-validation]] === Customizing Jwt Client Assertion Validation `JwtClientAssertionDecoderFactory.DEFAULT_JWT_VALIDATOR_FACTORY` is the default factory that provides an `OAuth2TokenValidator` for the specified `RegisteredClient` and is used for validating the `iss`, `sub`, `aud`, `exp` and `nbf` claims of the `Jwt` client assertion. `JwtClientAssertionDecoderFactory` provides the ability to override the default `Jwt` client assertion validation by supplying a custom factory of type `Function>` to `setJwtValidatorFactory()`. [NOTE] `JwtClientAssertionDecoderFactory` is the default `JwtDecoderFactory` used by `JwtClientAssertionAuthenticationProvider` that provides a `JwtDecoder` for the specified `RegisteredClient` and is used for authenticating a `Jwt` Bearer Token during OAuth2 client authentication. A common use case for customizing `JwtClientAssertionDecoderFactory` is to validate additional claims in the `Jwt` client assertion. The following example shows how to configure `JwtClientAssertionAuthenticationProvider` with a customized `JwtClientAssertionDecoderFactory` that validates an additional claim in the `Jwt` client assertion: [source,java] ---- @Bean public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception { OAuth2AuthorizationServerConfigurer authorizationServerConfigurer = OAuth2AuthorizationServerConfigurer.authorizationServer(); http .securityMatcher(authorizationServerConfigurer.getEndpointsMatcher()) .with(authorizationServerConfigurer, (authorizationServer) -> authorizationServer .clientAuthentication(clientAuthentication -> clientAuthentication .authenticationProviders(configureJwtClientAssertionValidator()) ) ); return http.build(); } private Consumer> configureJwtClientAssertionValidator() { return (authenticationProviders) -> authenticationProviders.forEach((authenticationProvider) -> { if (authenticationProvider instanceof JwtClientAssertionAuthenticationProvider) { // Customize JwtClientAssertionDecoderFactory JwtClientAssertionDecoderFactory jwtDecoderFactory = new JwtClientAssertionDecoderFactory(); Function> jwtValidatorFactory = (registeredClient) -> new DelegatingOAuth2TokenValidator<>( // Use default validators JwtClientAssertionDecoderFactory.DEFAULT_JWT_VALIDATOR_FACTORY.apply(registeredClient), // Add custom validator new JwtClaimValidator<>("claim", "value"::equals)); jwtDecoderFactory.setJwtValidatorFactory(jwtValidatorFactory); ((JwtClientAssertionAuthenticationProvider) authenticationProvider) .setJwtDecoderFactory(jwtDecoderFactory); } }); } ---- [[configuring-client-authentication-customizing-mutual-tls-client-authentication]] === Customizing Mutual-TLS Client Authentication `X509ClientCertificateAuthenticationProvider` is used for authenticating the client `X509Certificate` chain received when `ClientAuthenticationMethod.TLS_CLIENT_AUTH` or `ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH` method is used during OAuth2 client authentication. It is also composed with a _"Certificate Verifier"_, which is used to verify the contents of the client `X509Certificate` after the TLS handshake has successfully completed. [[customizing-mutual-tls-client-authentication-pki-mutual-tls-method]] ==== PKI Mutual-TLS Method For the PKI Mutual-TLS (`ClientAuthenticationMethod.TLS_CLIENT_AUTH`) method, the default implementation of the certificate verifier verifies the subject distinguished name of the client `X509Certificate` against the setting `RegisteredClient.getClientSettings.getX509CertificateSubjectDN()`. If you need to verify another attribute of the client `X509Certificate`, for example, a Subject Alternative Name (SAN) entry, the following example shows how to configure `X509ClientCertificateAuthenticationProvider` with a custom implementation of a certificate verifier: [source,java] ---- @Bean public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception { OAuth2AuthorizationServerConfigurer authorizationServerConfigurer = OAuth2AuthorizationServerConfigurer.authorizationServer(); http .securityMatcher(authorizationServerConfigurer.getEndpointsMatcher()) .with(authorizationServerConfigurer, (authorizationServer) -> authorizationServer .clientAuthentication(clientAuthentication -> clientAuthentication .authenticationProviders(configureX509ClientCertificateVerifier()) ) ); return http.build(); } private Consumer> configureX509ClientCertificateVerifier() { return (authenticationProviders) -> authenticationProviders.forEach((authenticationProvider) -> { if (authenticationProvider instanceof X509ClientCertificateAuthenticationProvider) { Consumer certificateVerifier = (clientAuthenticationContext) -> { OAuth2ClientAuthenticationToken clientAuthentication = clientAuthenticationContext.getAuthentication(); RegisteredClient registeredClient = clientAuthenticationContext.getRegisteredClient(); X509Certificate[] clientCertificateChain = (X509Certificate[]) clientAuthentication.getCredentials(); X509Certificate clientCertificate = clientCertificateChain[0]; // TODO Verify Subject Alternative Name (SAN) entry }; ((X509ClientCertificateAuthenticationProvider) authenticationProvider) .setCertificateVerifier(certificateVerifier); } }); } ---- [[customizing-mutual-tls-client-authentication-self-signed-certificate-mutual-tls-method]] ==== Self-Signed Certificate Mutual-TLS Method For the Self-Signed Certificate Mutual-TLS (`ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH`) method, the default implementation of the certificate verifier will retrieve the client's JSON Web Key Set using the setting `RegisteredClient.getClientSettings.getJwkSetUrl()` and expect to find a match against the client `X509Certificate` received during the TLS handshake. [NOTE] The `RegisteredClient.getClientSettings.getJwkSetUrl()` setting is used to retrieve the client's certificates via a JSON Web Key (JWK) Set. A certificate is represented with the `x5c` parameter of an individual JWK within the set. [[customizing-mutual-tls-client-authentication-client-certificate-bound-access-tokens]] ==== Client Certificate-Bound Access Tokens When Mutual-TLS client authentication is used at the token endpoint, the authorization server is able to bind the issued access token to the client's `X509Certificate`. The binding is accomplished by computing the SHA-256 thumbprint of the client's `X509Certificate` and associating the thumbprint with the access token. For example, a JWT access token would include a `x5t#S256` claim, containing the `X509Certificate` thumbprint, within the top-level `cnf` (confirmation method) claim. Binding the access token to the client's `X509Certificate` provides the ability to implement a proof-of-possession mechanism during protected resource access. For example, the protected resource would obtain the client's `X509Certificate` used during Mutual-TLS authentication and then verify that the certificate thumbprint matches the `x5t#S256` claim associated with the access token. The following example shows how to enable certificate-bound access tokens for a client: [source,java] ---- RegisteredClient mtlsClient = RegisteredClient.withId(UUID.randomUUID().toString()) .clientId("mtls-client") .clientAuthenticationMethod(ClientAuthenticationMethod.TLS_CLIENT_AUTH) .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS) .scope("scope-a") .clientSettings( ClientSettings.builder() .x509CertificateSubjectDN("CN=mtls-client,OU=Spring Samples,O=Spring,C=US") .build() ) .tokenSettings( TokenSettings.builder() .x509CertificateBoundAccessTokens(true) .build() ) .build(); ----