Migrate docs to Antora

Issue gh-1295
This commit is contained in:
Rob Winch
2023-07-03 13:36:26 -05:00
committed by Steve Riesenberg
parent ec3d4fa7e1
commit 0f0424ad2a
62 changed files with 327 additions and 198 deletions

View File

@@ -0,0 +1 @@
../../../src

View File

@@ -0,0 +1 @@
../../../../samples

View File

@@ -0,0 +1,12 @@
* xref:index.adoc[]
* xref:getting-help.adoc[]
* xref:getting-started.adoc[]
* xref:configuration-model.adoc[]
* xref:core-model-components.adoc[]
* xref:protocol-endpoints.adoc[]
* xref:how-to.adoc[]
** xref:guides/how-to-ext-grant-type.adoc[]
** xref:guides/how-to-jpa.adoc[]
** xref:guides/how-to-pkce.adoc[]
** xref:guides/how-to-social-login.adoc[]
** xref:guides/how-to-userinfo.adoc[]

View File

@@ -0,0 +1,322 @@
[[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.
[TIP]
`OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(HttpSecurity)` is a convenience (`static`) utility method that applies the default OAuth2 security configuration to `HttpSecurity`.
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<SecurityContext>` `@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<RegisteredClient> registrations = ...
return new InMemoryRegisteredClientRepository(registrations);
}
@Bean
public JWKSource<SecurityContext> 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 {
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
.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<SecurityContext>)` 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<SecurityContext> 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 =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
authorizationServerConfigurer
.registeredClientRepository(registeredClientRepository) <1>
.authorizationService(authorizationService) <2>
.authorizationConsentService(authorizationConsentService) <3>
.authorizationServerSettings(authorizationServerSettings) <4>
.tokenGenerator(tokenGenerator) <5>
.clientAuthentication(clientAuthentication -> { }) <6>
.authorizationEndpoint(authorizationEndpoint -> { }) <7>
.deviceAuthorizationEndpoint(deviceAuthorizationEndpoint -> { }) <8>
.deviceVerificationEndpoint(deviceVerificationEndpoint -> { }) <9>
.tokenEndpoint(tokenEndpoint -> { }) <10>
.tokenIntrospectionEndpoint(tokenIntrospectionEndpoint -> { }) <11>
.tokenRevocationEndpoint(tokenRevocationEndpoint -> { }) <12>
.authorizationServerMetadataEndpoint(authorizationServerMetadataEndpoint -> { }) <13>
.oidc(oidc -> oidc
.providerConfigurationEndpoint(providerConfigurationEndpoint -> { }) <14>
.logoutEndpoint(logoutEndpoint -> { }) <15>
.userInfoEndpoint(userInfoEndpoint -> { }) <16>
.clientRegistrationEndpoint(clientRegistrationEndpoint -> { }) <17>
);
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> `deviceAuthorizationEndpoint()`: The configurer for the xref:protocol-endpoints.adoc#oauth2-device-authorization-endpoint[OAuth2 Device Authorization endpoint].
<9> `deviceVerificationEndpoint()`: The configurer for the xref:protocol-endpoints.adoc#oauth2-device-verification-endpoint[OAuth2 Device Verification endpoint].
<10> `tokenEndpoint()`: The configurer for the xref:protocol-endpoints.adoc#oauth2-token-endpoint[OAuth2 Token endpoint].
<11> `tokenIntrospectionEndpoint()`: The configurer for the xref:protocol-endpoints.adoc#oauth2-token-introspection-endpoint[OAuth2 Token Introspection endpoint].
<12> `tokenRevocationEndpoint()`: The configurer for the xref:protocol-endpoints.adoc#oauth2-token-revocation-endpoint[OAuth2 Token Revocation endpoint].
<13> `authorizationServerMetadataEndpoint()`: The configurer for the xref:protocol-endpoints.adoc#oauth2-authorization-server-metadata-endpoint[OAuth2 Authorization Server Metadata endpoint].
<14> `providerConfigurationEndpoint()`: The configurer for the xref:protocol-endpoints.adoc#oidc-provider-configuration-endpoint[OpenID Connect 1.0 Provider Configuration endpoint].
<15> `logoutEndpoint()`: The configurer for the xref:protocol-endpoints.adoc#oidc-logout-endpoint[OpenID Connect 1.0 Logout endpoint].
<16> `userInfoEndpoint()`: The configurer for the xref:protocol-endpoints.adoc#oidc-user-info-endpoint[OpenID Connect 1.0 UserInfo endpoint].
<17> `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")
.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")
.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 =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
authorizationServerConfigurer
.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`, and `none` (public clients).
`OAuth2ClientAuthenticationFilter` is configured with the following defaults:
* `*AuthenticationConverter*` -- A `DelegatingAuthenticationConverter` composed of `JwtClientAssertionAuthenticationConverter`, `ClientSecretBasicAuthenticationConverter`, `ClientSecretPostAuthenticationConverter`, and `PublicClientAuthenticationConverter`.
* `*AuthenticationManager*` -- An `AuthenticationManager` composed of `JwtClientAssertionAuthenticationProvider`, `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<Jwt>` 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<RegisteredClient, OAuth2TokenValidator<Jwt>>` 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 =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
authorizationServerConfigurer
.clientAuthentication(clientAuthentication ->
clientAuthentication
.authenticationProviders(configureJwtClientAssertionValidator())
);
return http.build();
}
private Consumer<List<AuthenticationProvider>> configureJwtClientAssertionValidator() {
return (authenticationProviders) ->
authenticationProviders.forEach((authenticationProvider) -> {
if (authenticationProvider instanceof JwtClientAssertionAuthenticationProvider) {
// Customize JwtClientAssertionDecoderFactory
JwtClientAssertionDecoderFactory jwtDecoderFactory = new JwtClientAssertionDecoderFactory();
Function<RegisteredClient, OAuth2TokenValidator<Jwt>> 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);
}
});
}
----

View File

@@ -0,0 +1,526 @@
[[core-model-components]]
= Core Model / Components
[[registered-client]]
== RegisteredClient
A `RegisteredClient` is a representation of a client that is https://datatracker.ietf.org/doc/html/rfc6749#section-2[registered] with the authorization server.
A client must be registered with the authorization server before it can initiate an authorization grant flow, such as `authorization_code` or `client_credentials`.
During client registration, the client is assigned a unique https://datatracker.ietf.org/doc/html/rfc6749#section-2.2[client identifier], (optionally) a client secret (depending on https://datatracker.ietf.org/doc/html/rfc6749#section-2.1[client type]), and metadata associated with its unique client identifier.
The client's metadata can range from human-facing display strings (such as client name) to items specific to a protocol flow (such as the list of valid redirect URIs).
[TIP]
The corresponding client registration model in Spring Security's OAuth2 Client support is {spring-security-reference-base-url}/servlet/oauth2/client/core.html#oauth2Client-client-registration[ClientRegistration].
The primary purpose of a client is to request access to protected resources.
The client first requests an access token by authenticating with the authorization server and presenting the authorization grant.
The authorization server authenticates the client and authorization grant, and, if they are valid, issues an access token.
The client can now request the protected resource from the resource server by presenting the access token.
The following example shows how to configure a `RegisteredClient` that is allowed to perform the https://datatracker.ietf.org/doc/html/rfc6749#section-4.1[authorization_code grant] flow to request an access token:
[source,java]
----
RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
.clientId("client-a")
.clientSecret("{noop}secret") <1>
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUri("http://127.0.0.1:8080/authorized")
.scope("scope-a")
.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
.build();
----
<1> `\{noop\}` represents the `PasswordEncoder` id for Spring Security's {spring-security-reference-base-url}/features/authentication/password-storage.html#authentication-password-storage-dpe[NoOpPasswordEncoder].
The corresponding configuration in Spring Security's {spring-security-reference-base-url}/servlet/oauth2/client/index.html[OAuth2 Client support] is:
[source,yaml]
----
spring:
security:
oauth2:
client:
registration:
client-a:
provider: spring
client-id: client-a
client-secret: secret
authorization-grant-type: authorization_code
redirect-uri: "http://127.0.0.1:8080/authorized"
scope: scope-a
provider:
spring:
issuer-uri: http://localhost:9000
----
A `RegisteredClient` has metadata (attributes) associated with its unique Client Identifier and is defined as follows:
[source,java]
----
public class RegisteredClient implements Serializable {
private String id; <1>
private String clientId; <2>
private Instant clientIdIssuedAt; <3>
private String clientSecret; <4>
private Instant clientSecretExpiresAt; <5>
private String clientName; <6>
private Set<ClientAuthenticationMethod> clientAuthenticationMethods; <7>
private Set<AuthorizationGrantType> authorizationGrantTypes; <8>
private Set<String> redirectUris; <9>
private Set<String> postLogoutRedirectUris; <10>
private Set<String> scopes; <11>
private ClientSettings clientSettings; <12>
private TokenSettings tokenSettings; <13>
...
}
----
<1> `id`: The ID that uniquely identifies the `RegisteredClient`.
<2> `clientId`: The client identifier.
<3> `clientIdIssuedAt`: The time at which the client identifier was issued.
<4> `clientSecret`: The client's secret. The value should be encoded using Spring Security's {spring-security-reference-base-url}/features/authentication/password-storage.html#authentication-password-storage-dpe[PasswordEncoder].
<5> `clientSecretExpiresAt`: The time at which the client secret expires.
<6> `clientName`: A descriptive name used for the client. The name may be used in certain scenarios, such as when displaying the client name in the consent page.
<7> `clientAuthenticationMethods`: The authentication method(s) that the client may use. The supported values are `client_secret_basic`, `client_secret_post`, https://datatracker.ietf.org/doc/html/rfc7523[`private_key_jwt`], `client_secret_jwt`, and `none` https://datatracker.ietf.org/doc/html/rfc7636[(public clients)].
<8> `authorizationGrantTypes`: The https://datatracker.ietf.org/doc/html/rfc6749#section-1.3[authorization grant type(s)] that the client can use. The supported values are `authorization_code`, `client_credentials`, `refresh_token`, and `urn:ietf:params:oauth:grant-type:device_code`.
<9> `redirectUris`: The registered https://datatracker.ietf.org/doc/html/rfc6749#section-3.1.2[redirect URI(s)] that the client may use in redirect-based flows for example, `authorization_code` grant.
<10> `postLogoutRedirectUris`: The post logout redirect URI(s) that the client may use for logout.
<11> `scopes`: The scope(s) that the client is allowed to request.
<12> `clientSettings`: The custom settings for the client for example, require https://datatracker.ietf.org/doc/html/rfc7636[PKCE], require authorization consent, and others.
<13> `tokenSettings`: The custom settings for the OAuth2 tokens issued to the client for example, access/refresh token time-to-live, reuse refresh tokens, and others.
[[registered-client-repository]]
== RegisteredClientRepository
The `RegisteredClientRepository` is the central component where new clients can be registered and existing clients can be queried.
It is used by other components when following a specific protocol flow, such as client authentication, authorization grant processing, token introspection, dynamic client registration, and others.
The provided implementations of `RegisteredClientRepository` are `InMemoryRegisteredClientRepository` and `JdbcRegisteredClientRepository`.
The `InMemoryRegisteredClientRepository` implementation stores `RegisteredClient` instances in-memory and is recommended *ONLY* to be used during development and testing.
`JdbcRegisteredClientRepository` is a JDBC implementation that persists `RegisteredClient` instances by using `JdbcOperations`.
[NOTE]
The `RegisteredClientRepository` is a *REQUIRED* component.
The following example shows how to register a `RegisteredClientRepository` `@Bean`:
[source,java]
----
@Bean
public RegisteredClientRepository registeredClientRepository() {
List<RegisteredClient> registrations = ...
return new InMemoryRegisteredClientRepository(registrations);
}
----
Alternatively, you can configure the `RegisteredClientRepository` through the xref:configuration-model.adoc#customizing-the-configuration[`OAuth2AuthorizationServerConfigurer`]:
[source,java]
----
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
authorizationServerConfigurer
.registeredClientRepository(registeredClientRepository);
...
return http.build();
}
----
[NOTE]
The `OAuth2AuthorizationServerConfigurer` is useful when applying multiple configuration options simultaneously.
[[oauth2-authorization]]
== OAuth2Authorization
An `OAuth2Authorization` is a representation of an OAuth2 authorization, which holds state related to the authorization granted to a xref:core-model-components.adoc#registered-client[client], by the resource owner or itself in the case of the `client_credentials` authorization grant type.
[TIP]
The corresponding authorization model in Spring Security's OAuth2 Client support is {spring-security-reference-base-url}/servlet/oauth2/client/core.html#oauth2Client-authorized-client[OAuth2AuthorizedClient].
After the successful completion of an authorization grant flow, an `OAuth2Authorization` is created and associates an {spring-security-api-base-url}/org/springframework/security/oauth2/core/OAuth2AccessToken.html[`OAuth2AccessToken`], an (optional) {spring-security-api-base-url}/org/springframework/security/oauth2/core/OAuth2RefreshToken.html[`OAuth2RefreshToken`], and additional state specific to the executed authorization grant type.
The {spring-security-api-base-url}/org/springframework/security/oauth2/core/OAuth2Token.html[`OAuth2Token`] instances associated with an `OAuth2Authorization` vary, depending on the authorization grant type.
For the OAuth2 https://datatracker.ietf.org/doc/html/rfc6749#section-4.1[authorization_code grant], an `OAuth2AuthorizationCode`, an `OAuth2AccessToken`, and an (optional) `OAuth2RefreshToken` are associated.
For the OpenID Connect 1.0 https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth[authorization_code grant], an `OAuth2AuthorizationCode`, an {spring-security-api-base-url}/org/springframework/security/oauth2/core/oidc/OidcIdToken.html[`OidcIdToken`], an `OAuth2AccessToken`, and an (optional) `OAuth2RefreshToken` are associated.
For the OAuth2 https://datatracker.ietf.org/doc/html/rfc6749#section-4.4[client_credentials grant], only an `OAuth2AccessToken` is associated.
`OAuth2Authorization` and its attributes are defined as follows:
[source,java]
----
public class OAuth2Authorization implements Serializable {
private String id; <1>
private String registeredClientId; <2>
private String principalName; <3>
private AuthorizationGrantType authorizationGrantType; <4>
private Set<String> authorizedScopes; <5>
private Map<Class<? extends OAuth2Token>, Token<?>> tokens; <6>
private Map<String, Object> attributes; <7>
...
}
----
<1> `id`: The ID that uniquely identifies the `OAuth2Authorization`.
<2> `registeredClientId`: The ID that uniquely identifies the xref:core-model-components.adoc#registered-client[RegisteredClient].
<3> `principalName`: The principal name of the resource owner (or client).
<4> `authorizationGrantType`: The `AuthorizationGrantType` used.
<5> `authorizedScopes`: The `Set` of scope(s) authorized for the client.
<6> `tokens`: The `OAuth2Token` instances (and associated metadata) specific to the executed authorization grant type.
<7> `attributes`: The additional attributes specific to the executed authorization grant type for example, the authenticated `Principal`, `OAuth2AuthorizationRequest`, and others.
`OAuth2Authorization` and its associated `OAuth2Token` instances have a set lifespan.
A newly issued `OAuth2Token` is active and becomes inactive when it either expires or is invalidated (revoked).
The `OAuth2Authorization` is (implicitly) inactive when all associated `OAuth2Token` instances are inactive.
Each `OAuth2Token` is held in an `OAuth2Authorization.Token`, which provides accessors for `isExpired()`, `isInvalidated()`, and `isActive()`.
`OAuth2Authorization.Token` also provides `getClaims()`, which returns the claims (if any) associated with the `OAuth2Token`.
[[oauth2-authorization-service]]
== OAuth2AuthorizationService
The `OAuth2AuthorizationService` is the central component where new authorizations are stored and existing authorizations are queried.
It is used by other components when following a specific protocol flow for example, client authentication, authorization grant processing, token introspection, token revocation, dynamic client registration, and others.
The provided implementations of `OAuth2AuthorizationService` are `InMemoryOAuth2AuthorizationService` and `JdbcOAuth2AuthorizationService`.
The `InMemoryOAuth2AuthorizationService` implementation stores `OAuth2Authorization` instances in-memory and is recommended *ONLY* to be used during development and testing.
`JdbcOAuth2AuthorizationService` is a JDBC implementation that persists `OAuth2Authorization` instances by using `JdbcOperations`.
[NOTE]
The `OAuth2AuthorizationService` is an *OPTIONAL* component and defaults to `InMemoryOAuth2AuthorizationService`.
The following example shows how to register an `OAuth2AuthorizationService` `@Bean`:
[source,java]
----
@Bean
public OAuth2AuthorizationService authorizationService() {
return new InMemoryOAuth2AuthorizationService();
}
----
Alternatively, you can configure the `OAuth2AuthorizationService` through the xref:configuration-model.adoc#customizing-the-configuration[`OAuth2AuthorizationServerConfigurer`]:
[source,java]
----
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
authorizationServerConfigurer
.authorizationService(authorizationService);
...
return http.build();
}
----
[NOTE]
The `OAuth2AuthorizationServerConfigurer` is useful when applying multiple configuration options simultaneously.
[[oauth2-authorization-consent]]
== OAuth2AuthorizationConsent
An `OAuth2AuthorizationConsent` is a representation of an authorization "consent" (decision) from an https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.1[OAuth2 authorization request flow] for example, the `authorization_code` grant, which holds the authorities granted to a xref:core-model-components.adoc#registered-client[client] by the resource owner.
When authorizing access to a client, the resource owner may grant only a subset of the authorities requested by the client.
The typical use case is the `authorization_code` grant flow, in which the client requests scope(s) and the resource owner grants (or denies) access to the requested scope(s).
After the completion of an OAuth2 authorization request flow, an `OAuth2AuthorizationConsent` is created (or updated) and associates the granted authorities with the client and resource owner.
`OAuth2AuthorizationConsent` and its attributes are defined as follows:
[source,java]
----
public final class OAuth2AuthorizationConsent implements Serializable {
private final String registeredClientId; <1>
private final String principalName; <2>
private final Set<GrantedAuthority> authorities; <3>
...
}
----
<1> `registeredClientId`: The ID that uniquely identifies the xref:core-model-components.adoc#registered-client[RegisteredClient].
<2> `principalName`: The principal name of the resource owner.
<3> `authorities`: The authorities granted to the client by the resource owner. An authority can represent a scope, a claim, a permission, a role, and others.
[[oauth2-authorization-consent-service]]
== OAuth2AuthorizationConsentService
The `OAuth2AuthorizationConsentService` is the central component where new authorization consents are stored and existing authorization consents are queried.
It is primarily used by components that implement an OAuth2 authorization request flow for example, the `authorization_code` grant.
The provided implementations of `OAuth2AuthorizationConsentService` are `InMemoryOAuth2AuthorizationConsentService` and `JdbcOAuth2AuthorizationConsentService`.
The `InMemoryOAuth2AuthorizationConsentService` implementation stores `OAuth2AuthorizationConsent` instances in-memory and is recommended *ONLY* for development and testing.
`JdbcOAuth2AuthorizationConsentService` is a JDBC implementation that persists `OAuth2AuthorizationConsent` instances by using `JdbcOperations`.
[NOTE]
The `OAuth2AuthorizationConsentService` is an *OPTIONAL* component and defaults to `InMemoryOAuth2AuthorizationConsentService`.
The following example shows how to register an `OAuth2AuthorizationConsentService` `@Bean`:
[source,java]
----
@Bean
public OAuth2AuthorizationConsentService authorizationConsentService() {
return new InMemoryOAuth2AuthorizationConsentService();
}
----
Alternatively, you can configure the `OAuth2AuthorizationConsentService` through the xref:configuration-model.adoc#customizing-the-configuration[`OAuth2AuthorizationServerConfigurer`]:
[source,java]
----
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
authorizationServerConfigurer
.authorizationConsentService(authorizationConsentService);
...
return http.build();
}
----
[NOTE]
The `OAuth2AuthorizationServerConfigurer` is useful when applying multiple configuration options simultaneously.
[[oauth2-token-context]]
== OAuth2TokenContext
An `OAuth2TokenContext` is a context object that holds information associated with an `OAuth2Token` and is used by an xref:core-model-components.adoc#oauth2-token-generator[OAuth2TokenGenerator] and xref:core-model-components.adoc#oauth2-token-customizer[OAuth2TokenCustomizer].
`OAuth2TokenContext` provides the following accessors:
[source,java]
----
public interface OAuth2TokenContext extends Context {
default RegisteredClient getRegisteredClient() ... <1>
default <T extends Authentication> T getPrincipal() ... <2>
default AuthorizationServerContext getAuthorizationServerContext() ... <3>
@Nullable
default OAuth2Authorization getAuthorization() ... <4>
default Set<String> getAuthorizedScopes() ... <5>
default OAuth2TokenType getTokenType() ... <6>
default AuthorizationGrantType getAuthorizationGrantType() ... <7>
default <T extends Authentication> T getAuthorizationGrant() ... <8>
...
}
----
<1> `getRegisteredClient()`: The xref:core-model-components.adoc#registered-client[RegisteredClient] associated with the authorization grant.
<2> `getPrincipal()`: The `Authentication` instance of the resource owner (or client).
<3> `getAuthorizationServerContext()`: The xref:configuration-model.adoc#configuring-authorization-server-settings[`AuthorizationServerContext`] object that holds information of the Authorization Server runtime environment.
<4> `getAuthorization()`: The xref:core-model-components.adoc#oauth2-authorization[OAuth2Authorization] associated with the authorization grant.
<5> `getAuthorizedScopes()`: The scope(s) authorized for the client.
<6> `getTokenType()`: The `OAuth2TokenType` to generate. The supported values are `code`, `access_token`, `refresh_token`, and `id_token`.
<7> `getAuthorizationGrantType()`: The `AuthorizationGrantType` associated with the authorization grant.
<8> `getAuthorizationGrant()`: The `Authentication` instance used by the `AuthenticationProvider` that processes the authorization grant.
[[oauth2-token-generator]]
== OAuth2TokenGenerator
An `OAuth2TokenGenerator` is responsible for generating an `OAuth2Token` from the information contained in the provided xref:core-model-components.adoc#oauth2-token-context[OAuth2TokenContext].
The `OAuth2Token` generated primarily depends on the type of `OAuth2TokenType` specified in the `OAuth2TokenContext`.
For example, when the `value` for `OAuth2TokenType` is:
* `code`, then `OAuth2AuthorizationCode` is generated.
* `access_token`, then `OAuth2AccessToken` is generated.
* `refresh_token`, then `OAuth2RefreshToken` is generated.
* `id_token`, then `OidcIdToken` is generated.
Furthermore, the format of the generated `OAuth2AccessToken` varies, depending on the `TokenSettings.getAccessTokenFormat()` configured for the xref:core-model-components.adoc#registered-client[RegisteredClient].
If the format is `OAuth2TokenFormat.SELF_CONTAINED` (the default), then a `Jwt` is generated.
If the format is `OAuth2TokenFormat.REFERENCE`, then an "opaque" token is generated.
Finally, if the generated `OAuth2Token` has a set of claims and implements `ClaimAccessor`, the claims are made accessible from xref:core-model-components.adoc#oauth2-authorization[OAuth2Authorization.Token.getClaims()].
The `OAuth2TokenGenerator` is primarily used by components that implement authorization grant processing for example, `authorization_code`, `client_credentials`, and `refresh_token`.
The provided implementations are `OAuth2AccessTokenGenerator`, `OAuth2RefreshTokenGenerator`, and `JwtGenerator`.
The `OAuth2AccessTokenGenerator` generates an "opaque" (`OAuth2TokenFormat.REFERENCE`) access token, and the `JwtGenerator` generates a `Jwt` (`OAuth2TokenFormat.SELF_CONTAINED`).
[NOTE]
The `OAuth2TokenGenerator` is an *OPTIONAL* component and defaults to a `DelegatingOAuth2TokenGenerator` composed of an `OAuth2AccessTokenGenerator` and `OAuth2RefreshTokenGenerator`.
[NOTE]
If a `JwtEncoder` `@Bean` or `JWKSource<SecurityContext>` `@Bean` is registered, then a `JwtGenerator` is additionally composed in the `DelegatingOAuth2TokenGenerator`.
The `OAuth2TokenGenerator` provides great flexibility, as it can support any custom token format for `access_token` and `refresh_token`.
The following example shows how to register an `OAuth2TokenGenerator` `@Bean`:
[source,java]
----
@Bean
public OAuth2TokenGenerator<?> tokenGenerator() {
JwtEncoder jwtEncoder = ...
JwtGenerator jwtGenerator = new JwtGenerator(jwtEncoder);
OAuth2AccessTokenGenerator accessTokenGenerator = new OAuth2AccessTokenGenerator();
OAuth2RefreshTokenGenerator refreshTokenGenerator = new OAuth2RefreshTokenGenerator();
return new DelegatingOAuth2TokenGenerator(
jwtGenerator, accessTokenGenerator, refreshTokenGenerator);
}
----
Alternatively, you can configure the `OAuth2TokenGenerator` through the xref:configuration-model.adoc#customizing-the-configuration[`OAuth2AuthorizationServerConfigurer`]:
[source,java]
----
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
authorizationServerConfigurer
.tokenGenerator(tokenGenerator);
...
return http.build();
}
----
[NOTE]
The `OAuth2AuthorizationServerConfigurer` is useful when applying multiple configuration options simultaneously.
[[oauth2-token-customizer]]
== OAuth2TokenCustomizer
An `OAuth2TokenCustomizer` provides the ability to customize the attributes of an `OAuth2Token`, which are accessible in the provided xref:core-model-components.adoc#oauth2-token-context[OAuth2TokenContext].
It is used by an xref:core-model-components.adoc#oauth2-token-generator[OAuth2TokenGenerator] to let it customize the attributes of the `OAuth2Token` before it is generated.
An `OAuth2TokenCustomizer<OAuth2TokenClaimsContext>` declared with a generic type of `OAuth2TokenClaimsContext` (`implements OAuth2TokenContext`) provides the ability to customize the claims of an "opaque" `OAuth2AccessToken`.
`OAuth2TokenClaimsContext.getClaims()` provides access to the `OAuth2TokenClaimsSet.Builder`, allowing the ability to add, replace, and remove claims.
The following example shows how to implement an `OAuth2TokenCustomizer<OAuth2TokenClaimsContext>` and configure it with an `OAuth2AccessTokenGenerator`:
[source,java]
----
@Bean
public OAuth2TokenGenerator<?> tokenGenerator() {
JwtEncoder jwtEncoder = ...
JwtGenerator jwtGenerator = new JwtGenerator(jwtEncoder);
OAuth2AccessTokenGenerator accessTokenGenerator = new OAuth2AccessTokenGenerator();
accessTokenGenerator.setAccessTokenCustomizer(accessTokenCustomizer());
OAuth2RefreshTokenGenerator refreshTokenGenerator = new OAuth2RefreshTokenGenerator();
return new DelegatingOAuth2TokenGenerator(
jwtGenerator, accessTokenGenerator, refreshTokenGenerator);
}
@Bean
public OAuth2TokenCustomizer<OAuth2TokenClaimsContext> accessTokenCustomizer() {
return context -> {
OAuth2TokenClaimsSet.Builder claims = context.getClaims();
// Customize claims
};
}
----
[NOTE]
If the `OAuth2TokenGenerator` is not provided as a `@Bean` or is not configured through the `OAuth2AuthorizationServerConfigurer`, an `OAuth2TokenCustomizer<OAuth2TokenClaimsContext>` `@Bean` will automatically be configured with an `OAuth2AccessTokenGenerator`.
An `OAuth2TokenCustomizer<JwtEncodingContext>` declared with a generic type of `JwtEncodingContext` (`implements OAuth2TokenContext`) provides the ability to customize the headers and claims of a `Jwt`.
`JwtEncodingContext.getHeaders()` provides access to the `JwsHeader.Builder`, allowing the ability to add, replace, and remove headers.
`JwtEncodingContext.getClaims()` provides access to the `JwtClaimsSet.Builder`, allowing the ability to add, replace, and remove claims.
The following example shows how to implement an `OAuth2TokenCustomizer<JwtEncodingContext>` and configure it with a `JwtGenerator`:
[source,java]
----
@Bean
public OAuth2TokenGenerator<?> tokenGenerator() {
JwtEncoder jwtEncoder = ...
JwtGenerator jwtGenerator = new JwtGenerator(jwtEncoder);
jwtGenerator.setJwtCustomizer(jwtCustomizer());
OAuth2AccessTokenGenerator accessTokenGenerator = new OAuth2AccessTokenGenerator();
OAuth2RefreshTokenGenerator refreshTokenGenerator = new OAuth2RefreshTokenGenerator();
return new DelegatingOAuth2TokenGenerator(
jwtGenerator, accessTokenGenerator, refreshTokenGenerator);
}
@Bean
public OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer() {
return context -> {
JwsHeader.Builder headers = context.getHeaders();
JwtClaimsSet.Builder claims = context.getClaims();
if (context.getTokenType().equals(OAuth2TokenType.ACCESS_TOKEN)) {
// Customize headers/claims for access_token
} else if (context.getTokenType().getValue().equals(OidcParameterNames.ID_TOKEN)) {
// Customize headers/claims for id_token
}
};
}
----
[NOTE]
If the `OAuth2TokenGenerator` is not provided as a `@Bean` or is not configured through the `OAuth2AuthorizationServerConfigurer`, an `OAuth2TokenCustomizer<JwtEncodingContext>` `@Bean` will automatically be configured with a `JwtGenerator`.
[TIP]
For an example showing how you can xref:guides/how-to-userinfo.adoc#customize-id-token[customize the ID token], see the guide xref:guides/how-to-userinfo.adoc[How-to: Customize the OpenID Connect 1.0 UserInfo response].
[[session-registry]]
== SessionRegistry
If OpenID Connect 1.0 is enabled, a `SessionRegistry` instance is used to track authenticated sessions.
The `SessionRegistry` is used by the default implementation of `SessionAuthenticationStrategy` associated to the xref:protocol-endpoints.adoc#oauth2-authorization-endpoint[OAuth2 Authorization Endpoint] for registering new authenticated sessions.
[NOTE]
If a `SessionRegistry` `@Bean` is not registered, the default implementation `SessionRegistryImpl` will be used.
[IMPORTANT]
If a `SessionRegistry` `@Bean` is registered and is an instance of `SessionRegistryImpl`, a `HttpSessionEventPublisher` `@Bean` *SHOULD* also be registered as it's responsible for notifying `SessionRegistryImpl` of session lifecycle events, for example, `SessionDestroyedEvent`, to provide the ability to remove the `SessionInformation` instance.
When a logout is requested by an End-User, the xref:protocol-endpoints.adoc#oidc-logout-endpoint[OpenID Connect 1.0 Logout Endpoint] uses the `SessionRegistry` to lookup the `SessionInformation` associated to the authenticated End-User to perform the logout.
If Spring Security's {spring-security-reference-base-url}/servlet/authentication/session-management.html#ns-concurrent-sessions[Concurrent Session Control] feature is being used, it is *RECOMMENDED* to register a `SessionRegistry` `@Bean` to ensure it's shared between Spring Security's Concurrent Session Control and Spring Authorization Server's Logout feature.
The following example shows how to register a `SessionRegistry` `@Bean` and `HttpSessionEventPublisher` `@Bean` (required by `SessionRegistryImpl`):
[source,java]
----
@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}
----

View File

@@ -0,0 +1,24 @@
[[getting-help]]
= Getting Help
:page-section-summary-toc: 1
[[community]]
== Community
Welcome to the https://docs.spring.io/spring-security/reference/community.html[Spring Security Community].
Spring Authorization Server is an open source project led by the Spring Security team.
If you need help with Spring Authorization Server, we are here to help.
[[resources]]
== Resources
The following are some of the best ways to get help:
* Try the xref:how-to.adoc[How-to guides]. They provide solutions to the most common questions.
* Learn the Spring Security basics that Spring Authorization Server builds on. If you are starting out with Spring Security, check the https://spring.io/projects/spring-security#learn[reference documentation] or try one of the https://github.com/spring-projects/spring-security-samples[samples].
* Read through xref:index.adoc[this documentation].
* Try one of our many https://github.com/spring-projects/spring-authorization-server/tree/main/samples[sample applications].
* Ask a question on Stack Overflow with the https://stackoverflow.com/questions/tagged/spring-authorization-server[`spring-authorization-server`] tag.
* Report bugs and enhancement requests on https://github.com/spring-projects/spring-authorization-server/issues[GitHub].
NOTE: Spring Authorization Server is open source, including the documentation. If you find problems with the docs or if you want to improve them, please https://github.com/spring-projects/spring-authorization-server[get involved].

View File

@@ -0,0 +1,107 @@
[[getting-started]]
= Getting Started
If you are just getting started with Spring Authorization Server, the following sections walk you through creating your first application.
[[system-requirements]]
== System Requirements
Spring Authorization Server requires a Java 17 or higher Runtime Environment.
[[installing-spring-authorization-server]]
== Installing Spring Authorization Server
Spring Authorization Server can be used anywhere you already use https://docs.spring.io/spring-security/reference/prerequisites.html[Spring Security].
The easiest way to begin using Spring Authorization Server is by creating a https://spring.io/projects/spring-boot[Spring Boot]-based application.
You can use https://start.spring.io[start.spring.io] to generate a basic project or use the https://github.com/spring-projects/spring-authorization-server/tree/main/samples/default-authorizationserver[default authorization server sample] as a guide.
Then add Spring Boot's starter for Spring Authorization Server as a dependency:
[tabs]
======
Maven::
+
[[spring-boot-maven-dependency]]
[source,xml,role="primary",subs="attributes,verbatim"]
----
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-authorization-server</artifactId>
</dependency>
----
Gradle::
+
[[spring-boot-gradle-dependency]]
[source,gradle,role="secondary",subs="attributes,verbatim"]
----
implementation "org.springframework.boot:spring-boot-starter-oauth2-authorization-server"
----
======
TIP: See https://docs.spring.io/spring-boot/docs/current/reference/html/getting-started.html#getting-started.installing[Installing Spring Boot] for more information on using Spring Boot with Maven or Gradle.
Alternatively, you can add Spring Authorization Server without Spring Boot using the following example:
[tabs]
======
Maven::
+
[[maven-dependency]]
[source,xml,role="primary",subs="attributes,verbatim"]
----
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-authorization-server</artifactId>
<version>{spring-authorization-server-version}</version>
</dependency>
----
Gradle::
+
[[gradle-dependency]]
[source,gradle,role="secondary",subs="attributes,verbatim"]
----
implementation "org.springframework.security:spring-security-oauth2-authorization-server:{spring-authorization-server-version}"
----
======
[[developing-your-first-application]]
== Developing Your First Application
To get started, you need the minimum required components defined as a `@Bean`. When using the `spring-boot-starter-oauth2-authorization-server` dependency, define the following properties and Spring Boot will provide the necessary `@Bean` definitions for you:
[[application-yml]]
.application.yml
[source,yaml]
----
include::{docs-java}/sample/gettingstarted/application.yml[]
----
TIP: Beyond the Getting Started experience, most users will want to customize the default configuration. The xref:getting-started.adoc#defining-required-components[next section] demonstrates providing all of the necessary beans yourself.
[[defining-required-components]]
== Defining Required Components
If you want to customize the default configuration (regardless of whether you're using Spring Boot), you can define the minimum required components as a `@Bean` in a Spring `@Configuration`.
These components can be defined as follows:
[[sample.gettingStarted]]
.SecurityConfig.java
[source,java]
----
include::{docs-java}/sample/gettingstarted/SecurityConfig.java[]
----
This is a minimal configuration for getting started quickly. To understand what each component is used for, see the following descriptions:
<1> A Spring Security filter chain for the xref:protocol-endpoints.adoc[Protocol Endpoints].
<2> A Spring Security filter chain for https://docs.spring.io/spring-security/reference/servlet/authentication/index.html[authentication].
<3> An instance of {spring-security-api-base-url}/org/springframework/security/core/userdetails/UserDetailsService.html[`UserDetailsService`] for retrieving users to authenticate.
<4> An instance of xref:core-model-components.adoc#registered-client-repository[`RegisteredClientRepository`] for managing clients.
<5> An instance of `com.nimbusds.jose.jwk.source.JWKSource` for signing access tokens.
<6> An instance of `java.security.KeyPair` with keys generated on startup used to create the `JWKSource` above.
<7> An instance of {spring-security-api-base-url}/org/springframework/security/oauth2/jwt/JwtDecoder.html[`JwtDecoder`] for decoding signed access tokens.
<8> An instance of xref:configuration-model#configuring-authorization-server-settings[`AuthorizationServerSettings`] to configure Spring Authorization Server.

View File

@@ -0,0 +1,76 @@
[[how-to-extension-grant-type]]
= How-to: Implement an Extension Authorization Grant Type
:index-link: ../how-to.html
:docs-dir: ..
This guide shows how to extend xref:index.adoc[Spring Authorization Server] with an https://datatracker.ietf.org/doc/html/rfc6749#section-4.5[extension authorization grant type].
The purpose of this guide is to demonstrate how to implement an extension authorization grant type and configure it at the xref:protocol-endpoints.adoc#oauth2-token-endpoint[OAuth2 Token endpoint].
Extending Spring Authorization Server with a new authorization grant type requires implementing an `AuthenticationConverter` and `AuthenticationProvider`, and configuring both components at the xref:protocol-endpoints.adoc#oauth2-token-endpoint[OAuth2 Token endpoint].
In addition to the component implementations, a unique absolute URI needs to be assigned for use with the `grant_type` parameter.
* xref:guides/how-to-ext-grant-type.adoc#implement-authentication-converter[Implement AuthenticationConverter]
* xref:guides/how-to-ext-grant-type.adoc#implement-authentication-provider[Implement AuthenticationProvider]
* xref:guides/how-to-ext-grant-type.adoc#configure-token-endpoint[Configure OAuth2 Token Endpoint]
* xref:guides/how-to-ext-grant-type.adoc#request-access-token[Request the Access Token]
[[implement-authentication-converter]]
== Implement AuthenticationConverter
Assuming the absolute URI for the `grant_type` parameter is `urn:ietf:params:oauth:grant-type:custom_code` and the `code` parameter represents the authorization grant, the following example shows a sample implementation of the `AuthenticationConverter`:
.AuthenticationConverter
[source,java]
----
include::{examples-dir}/main/java/sample/extgrant/CustomCodeGrantAuthenticationConverter.java[]
----
TIP: Click on the "Expand folded text" icon in the code sample above to display the full example.
<1> If the `grant_type` parameter is *not* `urn:ietf:params:oauth:grant-type:custom_code`, then return `null`, allowing another `AuthenticationConverter` to process the token request.
<2> The `code` parameter contains the authorization grant.
<3> Return an instance of `CustomCodeGrantAuthenticationToken`, which is processed by xref:guides/how-to-ext-grant-type.adoc#implement-authentication-provider[`CustomCodeGrantAuthenticationProvider`].
[[implement-authentication-provider]]
== Implement AuthenticationProvider
The `AuthenticationProvider` implementation is responsible for validating the authorization grant, and if valid and authorized, issues an access token.
The following example shows a sample implementation of the `AuthenticationProvider`:
.AuthenticationProvider
[source,java]
----
include::{examples-dir}/main/java/sample/extgrant/CustomCodeGrantAuthenticationProvider.java[]
----
NOTE: `CustomCodeGrantAuthenticationProvider` processes `CustomCodeGrantAuthenticationToken`, which is created by xref:guides/how-to-ext-grant-type.adoc#implement-authentication-converter[`CustomCodeGrantAuthenticationConverter`].
[[configure-token-endpoint]]
== Configure OAuth2 Token Endpoint
The following example shows how to configure the xref:protocol-endpoints.adoc#oauth2-token-endpoint[OAuth2 Token endpoint] with the `AuthenticationConverter` and `AuthenticationProvider`:
.SecurityConfig
[source,java]
----
include::{examples-dir}/main/java/sample/extgrant/SecurityConfig.java[]
----
<1> Add the `AuthenticationConverter` to the OAuth2 Token endpoint configuration.
<2> Add the `AuthenticationProvider` to the OAuth2 Token endpoint configuration.
[[request-access-token]]
== Request the Access Token
The client can request the access token by making the following (authenticated) request to the OAuth2 Token endpoint:
[source,shell]
----
POST /oauth2/token HTTP/1.1
Authorization: Basic bWVzc2FnaW5nLWNsaWVudDpzZWNyZXQ=
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:custom_code&code=7QR49T1W3
----

View File

@@ -0,0 +1,271 @@
[[how-to-jpa]]
= How-to: Implement core services with JPA
:index-link: ../how-to.html
:docs-dir: ..
This guide shows how to implement the xref:core-model-components.adoc[core services] of xref:index.adoc[Spring Authorization Server] with JPA.
The purpose of this guide is to provide a starting point for implementing these services yourself, with the intention that you can make modifications to suit your needs.
* xref:guides/how-to-jpa.adoc#define-data-model[Define the data model]
* xref:guides/how-to-jpa.adoc#create-jpa-entities[Create JPA entities]
* xref:guides/how-to-jpa.adoc#create-spring-data-repositories[Create Spring Data repositories]
* xref:guides/how-to-jpa.adoc#implement-core-services[Implement core services]
[[define-data-model]]
== Define the data model
This guide provides a starting point for the data model and uses the simplest possible structure and data types.
To come up with the initial schema, we begin by reviewing the xref:core-model-components.adoc[domain objects] used by the core services.
[NOTE]
Except for token, state, metadata, settings, and claims values, we use the JPA default column length of 255 for all columns.
In reality, the length and even type of columns you use may need to be customized.
You are encouraged to experiment and test before deploying to production.
* xref:guides/how-to-jpa.adoc#client-schema[Client Schema]
* xref:guides/how-to-jpa.adoc#authorization-schema[Authorization Schema]
* xref:guides/how-to-jpa.adoc#authorization-consent-schema[Authorization Consent Schema]
[[client-schema]]
=== Client Schema
The xref:core-model-components.adoc#registered-client[`RegisteredClient`] domain object contains a few multi-valued fields and some settings fields that require storing arbitrary key/value data.
The following listing shows the `client` schema.
.Client Schema
[source,sql]
----
CREATE TABLE client (
id varchar(255) NOT NULL,
clientId varchar(255) NOT NULL,
clientIdIssuedAt timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL,
clientSecret varchar(255) DEFAULT NULL,
clientSecretExpiresAt timestamp DEFAULT NULL,
clientName varchar(255) NOT NULL,
clientAuthenticationMethods varchar(1000) NOT NULL,
authorizationGrantTypes varchar(1000) NOT NULL,
redirectUris varchar(1000) DEFAULT NULL,
postLogoutRedirectUris varchar(1000) DEFAULT NULL,
scopes varchar(1000) NOT NULL,
clientSettings varchar(2000) NOT NULL,
tokenSettings varchar(2000) NOT NULL,
PRIMARY KEY (id)
);
----
[[authorization-schema]]
=== Authorization Schema
The xref:core-model-components.adoc#oauth2-authorization[`OAuth2Authorization`] domain object is more complex and contains several multi-valued fields as well as numerous arbitrarily long token values, metadata, settings and claims values.
The built-in JDBC implementation utilizes a flattened structure that prefers performance over normalization, which we adopt here as well.
[CAUTION]
It has been difficult to find a flattened database schema that works well in all cases and with all database vendors.
You may need to normalize or heavily alter the following schema for your needs.
The following listing shows the `authorization` schema.
.Authorization Schema
[source,sql]
----
CREATE TABLE authorization (
id varchar(255) NOT NULL,
registeredClientId varchar(255) NOT NULL,
principalName varchar(255) NOT NULL,
authorizationGrantType varchar(255) NOT NULL,
authorizedScopes varchar(1000) DEFAULT NULL,
attributes varchar(4000) DEFAULT NULL,
state varchar(500) DEFAULT NULL,
authorizationCodeValue varchar(4000) DEFAULT NULL,
authorizationCodeIssuedAt timestamp DEFAULT NULL,
authorizationCodeExpiresAt timestamp DEFAULT NULL,
authorizationCodeMetadata varchar(2000) DEFAULT NULL,
accessTokenValue varchar(4000) DEFAULT NULL,
accessTokenIssuedAt timestamp DEFAULT NULL,
accessTokenExpiresAt timestamp DEFAULT NULL,
accessTokenMetadata varchar(2000) DEFAULT NULL,
accessTokenType varchar(255) DEFAULT NULL,
accessTokenScopes varchar(1000) DEFAULT NULL,
refreshTokenValue varchar(4000) DEFAULT NULL,
refreshTokenIssuedAt timestamp DEFAULT NULL,
refreshTokenExpiresAt timestamp DEFAULT NULL,
refreshTokenMetadata varchar(2000) DEFAULT NULL,
oidcIdTokenValue varchar(4000) DEFAULT NULL,
oidcIdTokenIssuedAt timestamp DEFAULT NULL,
oidcIdTokenExpiresAt timestamp DEFAULT NULL,
oidcIdTokenMetadata varchar(2000) DEFAULT NULL,
oidcIdTokenClaims varchar(2000) DEFAULT NULL,
userCodeValue varchar(4000) DEFAULT NULL,
userCodeIssuedAt timestamp DEFAULT NULL,
userCodeExpiresAt timestamp DEFAULT NULL,
userCodeMetadata varchar(2000) DEFAULT NULL,
deviceCodeValue varchar(4000) DEFAULT NULL,
deviceCodeIssuedAt timestamp DEFAULT NULL,
deviceCodeExpiresAt timestamp DEFAULT NULL,
deviceCodeMetadata varchar(2000) DEFAULT NULL,
PRIMARY KEY (id)
);
----
[[authorization-consent-schema]]
=== Authorization Consent Schema
The xref:core-model-components.adoc#oauth2-authorization-consent[`OAuth2AuthorizationConsent`] domain object is the simplest to model and contains only a single multi-valued field in addition to a composite key.
The following listing shows the `authorizationConsent` schema.
.Authorization Consent Schema
[source,sql]
----
CREATE TABLE authorizationConsent (
registeredClientId varchar(255) NOT NULL,
principalName varchar(255) NOT NULL,
authorities varchar(1000) NOT NULL,
PRIMARY KEY (registeredClientId, principalName)
);
----
[[create-jpa-entities]]
== Create JPA entities
The preceding schema examples provide a reference for the structure of the entities we need to create.
[NOTE]
The following entities are minimally annotated and are just examples.
They allow the schema to be created dynamically and therefore do not require the above sql scripts to be executed manually.
* xref:guides/how-to-jpa.adoc#client-entity[Client Entity]
* xref:guides/how-to-jpa.adoc#authorization-entity[Authorization Entity]
* xref:guides/how-to-jpa.adoc#authorization-consent-entity[Authorization Consent Entity]
[[client-entity]]
=== Client Entity
The following listing shows the `Client` entity, which is used to persist information mapped from the xref:core-model-components.adoc#registered-client[`RegisteredClient`] domain object.
[[sample.jpa.entity.client]]
.Client Entity
[source,java]
----
include::{examples-dir}/main/java/sample/jpa/entity/client/Client.java[]
----
[[authorization-entity]]
=== Authorization Entity
The following listing shows the `Authorization` entity, which is used to persist information mapped from the xref:core-model-components.adoc#oauth2-authorization[`OAuth2Authorization`] domain object.
[[sample.jpa.entity.authorization]]
.Authorization Entity
[source,java]
----
include::{examples-dir}/main/java/sample/jpa/entity/authorization/Authorization.java[]
----
[[authorization-consent-entity]]
=== Authorization Consent Entity
The following listing shows the `AuthorizationConsent` entity, which is used to persist information mapped from the xref:core-model-components.adoc#oauth2-authorization-consent[`OAuth2AuthorizationConsent`] domain object.
[[sample.jpa.entity.authorizationConsent]]
.Authorization Consent Entity
[source,java]
----
include::{examples-dir}/main/java/sample/jpa/entity/authorizationConsent/AuthorizationConsent.java[]
----
[[create-spring-data-repositories]]
== Create Spring Data repositories
By closely examining the interfaces of each core service and reviewing the `Jdbc` implementations, we can derive a minimal set of queries needed for supporting a JPA version of each interface.
* xref:guides/how-to-jpa.adoc#client-repository[Client Repository]
* xref:guides/how-to-jpa.adoc#authorization-repository[Authorization Repository]
* xref:guides/how-to-jpa.adoc#authorization-consent-repository[Authorization Consent Repository]
[[client-repository]]
=== Client Repository
The following listing shows the `ClientRepository`, which is able to find a xref:guides/how-to-jpa.adoc#client-entity[`Client`] by the `id` and `clientId` fields.
[[sample.jpa.repository.client]]
.Client Repository
[source,java]
----
include::{examples-dir}/main/java/sample/jpa/repository/client/ClientRepository.java[]
----
[[authorization-repository]]
=== Authorization Repository
The following listing shows the `AuthorizationRepository`, which is able to find an xref:guides/how-to-jpa.adoc#authorization-entity[`Authorization`] by the `id` field as well as the `state`, `authorizationCodeValue`, `accessTokenValue`, `refreshTokenValue`, `userCodeValue` and `deviceCodeValue` token fields.
It also allows querying a combination of token fields.
[[sample.jpa.repository.authorization]]
.Authorization Repository
[source,java]
----
include::{examples-dir}/main/java/sample/jpa/repository/authorization/AuthorizationRepository.java[]
----
[[authorization-consent-repository]]
=== Authorization Consent Repository
The following listing shows the `AuthorizationConsentRepository`, which is able to find and delete an xref:guides/how-to-jpa.adoc#authorization-consent-entity[`AuthorizationConsent`] by the `registeredClientId` and `principalName` fields that form a composite primary key.
[[sample.jpa.repository.authorizationConsent]]
.Authorization Consent Repository
[source,java]
----
include::{examples-dir}/main/java/sample/jpa/repository/authorizationConsent/AuthorizationConsentRepository.java[]
----
[[implement-core-services]]
== Implement core services
With the above xref:guides/how-to-jpa.adoc#create-jpa-entities[entities] and xref:guides/how-to-jpa.adoc#create-spring-data-repositories[repositories], we can begin implementing the core services.
By reviewing the `Jdbc` implementations, we can derive a minimal set of internal utilities for converting to and from string values for enumerations and reading and writing JSON data for attributes, settings, metadata and claims fields.
[CAUTION]
Keep in mind that writing JSON data to text columns with a fixed length has proven problematic with the `Jdbc` implementations.
While these examples continue to do so, you may need to split these fields out into a separate table or data store that supports arbitrarily long data values.
* <<registered-client-repository>>
* xref:guides/how-to-jpa.adoc#authorization-service[Authorization Service]
* xref:guides/how-to-jpa.adoc#authorization-consent-service[Authorization Consent Service]
[[registered-client-repository]]
=== Registered Client Repository
The following listing shows the `JpaRegisteredClientRepository`, which uses a xref:guides/how-to-jpa.adoc#client-repository[`ClientRepository`] for persisting a xref:guides/how-to-jpa.adoc#client-entity[`Client`] and maps to and from the xref:core-model-components.adoc#registered-client[`RegisteredClient`] domain object.
[[sample.jpa.service.client]]
.`RegisteredClientRepository` Implementation
[source,java]
----
include::{examples-dir}/main/java/sample/jpa/service/client/JpaRegisteredClientRepository.java[]
----
[[authorization-service]]
=== Authorization Service
The following listing shows the `JpaOAuth2AuthorizationService`, which uses an xref:guides/how-to-jpa.adoc#authorization-repository[`AuthorizationRepository`] for persisting an xref:guides/how-to-jpa.adoc#authorization-entity[`Authorization`] and maps to and from the xref:core-model-components.adoc#oauth2-authorization[`OAuth2Authorization`] domain object.
[[sample.jpa.service.authorization]]
.`OAuth2AuthorizationService` Implementation
[source,java]
----
include::{examples-dir}/main/java/sample/jpa/service/authorization/JpaOAuth2AuthorizationService.java[]
----
[[authorization-consent-service]]
=== Authorization Consent Service
The following listing shows the `JpaOAuth2AuthorizationConsentService`, which uses an xref:guides/how-to-jpa.adoc#authorization-consent-repository[`AuthorizationConsentRepository`] for persisting an xref:guides/how-to-jpa.adoc#authorization-consent-entity[`AuthorizationConsent`] and maps to and from the xref:core-model-components.adoc#oauth2-authorization-consent[`OAuth2AuthorizationConsent`] domain object.
[[sample.jpa.service.authorizationConsent]]
.`OAuth2AuthorizationConsentService` Implementation
[source,java]
----
include::{examples-dir}/main/java/sample/jpa/service/authorizationConsent/JpaOAuth2AuthorizationConsentService.java[]
----

View File

@@ -0,0 +1,82 @@
[[how-to-pkce]]
= How-to: Authenticate using a Single Page Application with PKCE
:index-link: ../how-to.html
:docs-dir: ..
This guide shows how to configure xref:index.adoc[Spring Authorization Server] to support a Single Page Application (SPA) with Proof Key for Code Exchange (PKCE).
The purpose of this guide is to demonstrate how to support a public client and require PKCE for client authentication.
NOTE: Spring Authorization Server will not issue refresh tokens for a public client. We recommend the backend for frontend (BFF) pattern as an alternative to exposing a public client. See https://github.com/spring-projects/spring-authorization-server/issues/297#issue-896744390[gh-297] for more information.
* xref:guides/how-to-pkce.adoc#enable-cors[Enable CORS]
* xref:guides/how-to-pkce.adoc#configure-public-client[Configure a Public Client]
* xref:guides/how-to-pkce.adoc#authenticate-with-client[Authenticate with the Client]
[[enable-cors]]
== Enable CORS
A SPA consists of static resources that can be deployed in a variety of ways.
It can be deployed separately from the backend such as with a CDN or separate web server, or it can be deployed along side the backend using Spring Boot.
When a SPA is hosted under a different domain, Cross Origin Resource Sharing (CORS) can be used to allow the application to communicate with the backend.
For example, if you have an Angular dev server running locally on port `4200`, you can define a `CorsConfigurationSource` `@Bean` and configure Spring Security to allow pre-flight requests using the `cors()` DSL as in the following example:
[[enable-cors-configuration]]
.Enable CORS
[source,java]
----
include::{examples-dir}/main/java/sample/pkce/SecurityConfig.java[]
----
TIP: Click on the "Expand folded text" icon in the code sample above to display the full example.
[[configure-public-client]]
== Configure a Public Client
A SPA cannot securely store credentials and therefore must be treated as a https://datatracker.ietf.org/doc/html/rfc6749#section-2.1[public client^].
Public clients should be required to use https://datatracker.ietf.org/doc/html/rfc7636#section-4[Proof Key for Code Exchange] (PKCE).
Continuing the xref:guides/how-to-pkce.adoc#enable-cors-configuration[earlier] example, you can configure Spring Authorization Server to support a public client using the Client Authentication Method `none` and require PKCE as in the following example:
[tabs]
======
Yaml::
+
[[configure-public-client-example]]
[source,yaml,role="primary"]
----
include::{examples-dir}/main/java/sample/pkce/application.yml[]
----
Java::
+
[source,java,role="secondary"]
----
include::{examples-dir}/main/java/sample/pkce/ClientConfig.java[tag=client,indent=0]
----
======
NOTE: The `requireProofKey` setting is helpful in situations where you forget to include the `code_challenge` and `code_challenge_method` query parameters because you will receive an error indicating PKCE is required during the xref:protocol-endpoints.adoc#oauth2-authorization-endpoint[Authorization Request] instead of a general client authentication error during the xref:protocol-endpoints.adoc#oauth2-token-endpoint[Token Request].
[[authenticate-with-client]]
== Authenticate with the Client
Once the server is configured to support a public client, a common question is: _How do I authenticate the client and get an access token?_
The short answer is: The same way you would with any other client.
NOTE: A SPA is a browser-based application and therefore uses the same redirection-based flow as any other client. This question is usually related to an expectation that authentication can be performed via a REST API, which is not the case with OAuth2.
A more detailed answer requires an understanding of the flow(s) involved in OAuth2 and OpenID Connect, in this case the Authorization Code flow.
The steps of the Authorization Code flow are as follows:
1. The client initiates an OAuth2 request via a redirect to the xref:protocol-endpoints.adoc#oauth2-authorization-endpoint[Authorization Endpoint]. For a public client, this step includes generating the `code_verifier` and calculating the `code_challenge`, which is then sent as a query parameter.
2. If the user is not authenticated, the authorization server will redirect to the login page. After authentication, the user is redirected back to the Authorization Endpoint again.
3. If the user has not consented to the requested scope(s) and consent is required, the consent page is displayed.
4. Once the user has consented, the authorization server generates an `authorization_code` and redirects back to the client via the `redirect_uri`.
5. The client obtains the `authorization_code` via a query parameter and performs a request to the xref:protocol-endpoints.adoc#oauth2-token-endpoint[Token Endpoint]. For a public client, this step includes sending the `code_verifier` parameter instead of credentials for authentication.
As you can see, the flow is fairly involved and this overview only scratches the surface.
TIP: It is recommended that you use a robust client-side library supported by your single-page app framework to handle the Authorization Code flow.

View File

@@ -0,0 +1,171 @@
[[how-to-social-login]]
= How-to: Authenticate using Social Login
:index-link: ../how-to.html
:docs-dir: ..
:github-ref: main
:github-base-url: https://github.com/spring-projects/spring-authorization-server/blob/{github-ref}
This guide shows how to configure xref:index.adoc[Spring Authorization Server] with a social login provider (such as Google, GitHub, etc.) for {spring-security-reference-base-url}/servlet/authentication/index.html[authentication].
The purpose of this guide is to demonstrate how to replace {spring-security-reference-base-url}/servlet/authentication/passwords/form.html[Form Login] with {spring-security-reference-base-url}/servlet/oauth2/login/index.html[OAuth 2.0 Login].
NOTE: Spring Authorization Server is built on {spring-security-reference-base-url}/index.html[Spring Security] and we will be using Spring Security concepts throughout this guide.
* xref:guides/how-to-social-login.adoc#register-social-login-provider[Register with Social Login Provider]
* xref:guides/how-to-social-login.adoc#configure-oauth2-login[Configure OAuth 2.0 Login]
* xref:guides/how-to-social-login.adoc#advanced-use-cases[Advanced Use Cases]
[[register-social-login-provider]]
== Register with Social Login Provider
To get started, you will need to set up an application with your chosen social login provider.
Common providers include:
* https://developers.google.com/identity/openid-connect/openid-connect#appsetup[Google]
* https://github.com/settings/developers[GitHub]
* https://developers.facebook.com/apps[Facebook]
* https://www.okta.com/developer/signup[Okta]
Follow the steps for your provider until you are asked to specify a Redirect URI.
To set up a Redirect URI, choose a `registrationId` (such as `google`, `my-client` or any other unique identifier you wish) which you will use to configure both Spring Security **and** your provider.
NOTE: The `registrationId` is a unique identifier for the `ClientRegistration` in Spring Security. The default Redirect URI template is `\{baseUrl\}/login/oauth2/code/\{registrationId\}`. See {spring-security-reference-base-url}/servlet/oauth2/login/core.html#oauth2login-sample-redirect-uri[Setting the Redirect URI] in the Spring Security reference for more information.
TIP: For example, testing locally on port `9000` with a `registrationId` of `google`, your Redirect URI would be `http://localhost:9000/login/oauth2/code/google`. Enter this value as the Redirect URI when setting up the application with your provider.
Once you've completed the set-up process with your social login provider, you should have obtained credentials (a Client ID and Client Secret).
In addition, you will need to reference the provider's documentation and take note of the following values:
* **Authorization URI**: The endpoint that is used to initiate the `authorization_code` flow at the provider.
* **Token URI**: The endpoint that is used to exchange an `authorization_code` for an `access_token` and optionally an `id_token`.
* **JWK Set URI**: The endpoint that is used to obtain keys for verifying the signature of a JWT, which is required when an `id_token` is available.
* **User Info URI**: The endpoint that is used to obtain user information, which is required when an `id_token` is not available.
* **User Name Attribute**: The claim in either the `id_token` or the User Info Response containing the username of the user.
[[configure-oauth2-login]]
== Configure OAuth 2.0 Login
Once you've xref:guides/how-to-social-login.adoc#register-social-login-provider[registered] with a social login provider, you can proceed to configuring Spring Security for {spring-security-reference-base-url}/servlet/oauth2/login/index.html[OAuth 2.0 Login].
* xref:guides/how-to-social-login.adoc#configure-oauth2-login-dependency[Add OAuth2 Client Dependency]
* xref:guides/how-to-social-login.adoc#configure-oauth2-login-client-registration[Register a Client]
* xref:guides/how-to-social-login.adoc#configure-oauth2-login-authentication[Configure Authentication]
[[configure-oauth2-login-dependency]]
=== Add OAuth2 Client Dependency
First, add the following dependency:
[tabs]
======
Maven::
+
[[configure-oauth2-login-maven-dependency]]
[source,xml,role="primary",subs="attributes,verbatim"]
----
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
----
Gradle::
+
[[configure-oauth2-login-gradle-dependency]]
[source,gradle,role="secondary",subs="attributes,verbatim"]
----
implementation "org.springframework.boot:spring-boot-starter-oauth2-client"
----
======
[[configure-oauth2-login-client-registration]]
=== Register a Client
Next, configure the `ClientRegistration` with the values obtained xref:guides/how-to-social-login.adoc#register-social-login-provider[earlier].
Using Okta as an example, configure the following properties:
[[configure-oauth2-login-okta-example]]
.application.yml
[source,yaml]
----
include::{examples-dir}/main/java/sample/sociallogin/application.yml[]
----
NOTE: The `registrationId` in the above example is `my-client`.
TIP: The above example demonstrates the *recommended* way to set the Provider URL, Client ID and Client Secret using environment variables (`OKTA_BASE_URL`, `OKTA_CLIENT_ID` and `OKTA_CLIENT_SECRET`). See {spring-boot-reference-base-url}/features.html#features.external-config[Externalized Configuration] in the Spring Boot reference for more information.
This simple example demonstrates a typical configuration, but some providers will require additional configuration.
For more information about configuring the `ClientRegistration`, see {spring-security-reference-base-url}/servlet/oauth2/login/core.html#oauth2login-boot-property-mappings[Spring Boot Property Mappings] in the Spring Security reference.
[[configure-oauth2-login-authentication]]
=== Configure Authentication
Finally, to configure Spring Authorization Server to use a social login provider for authentication, you can use `oauth2Login()` instead of `formLogin()`.
You can also automatically redirect an unauthenticated user to the provider by configuring `exceptionHandling()` with an `AuthenticationEntryPoint`.
Continuing our xref:guides/how-to-social-login.adoc#configure-oauth2-login-okta-example[earlier example], configure Spring Security using a `@Configuration` as in the following example:
.Configure OAuth 2.0 Login
[source,java]
----
include::{examples-dir}/main/java/sample/sociallogin/SecurityConfig.java[]
----
<1> A Spring Security filter chain for the xref:{docs-dir}/protocol-endpoints.adoc[Protocol Endpoints].
<2> Configure an `AuthenticationEntryPoint` for redirecting to the {spring-security-reference-base-url}/servlet/oauth2/login/advanced.html#oauth2login-advanced-login-page[OAuth 2.0 Login endpoint].
<3> A Spring Security filter chain for https://docs.spring.io/spring-security/reference/servlet/authentication/index.html[authentication].
<4> Configure {spring-security-reference-base-url}/servlet/oauth2/login/index.html[OAuth 2.0 Login] for authentication.
If you configured a `UserDetailsService` when xref:getting-started.adoc#developing-your-first-application[getting started], you can remove it now.
[[advanced-use-cases]]
== Advanced Use Cases
The https://github.com/spring-projects/spring-authorization-server/tree/{github-ref}/samples#demo-sample[demo authorization server sample^] demonstrates advanced configuration options for federating identity providers.
Select from the following use cases to see an example of each:
* I want to xref:guides/how-to-social-login.adoc#advanced-use-cases-capture-users[Capture Users in a Database]
* I want to xref:guides/how-to-social-login.adoc#advanced-use-cases-map-claims[Map Claims to an ID Token]
[[advanced-use-cases-capture-users]]
=== Capture Users in a Database
The following example `AuthenticationSuccessHandler` uses a custom component to capture users in a local database when they first log in:
.`FederatedIdentityAuthenticationSuccessHandler`
[source,java]
----
include::{samples-dir}/demo-authorizationserver/src/main/java/sample/federation/FederatedIdentityAuthenticationSuccessHandler.java[tags=imports;class]
----
Using the `AuthenticationSuccessHandler` above, you can plug in your own `Consumer<OAuth2User>` that can capture users in a database or other data store for concepts like Federated Account Linking or JIT Account Provisioning.
Here is an example that simply stores users in-memory:
.`UserRepositoryOAuth2UserHandler`
[source,java]
----
include::{samples-dir}/demo-authorizationserver/src/main/java/sample/federation/UserRepositoryOAuth2UserHandler.java[tags=imports;class]
----
[[advanced-use-cases-map-claims]]
=== Map Claims to an ID Token
The following example `OAuth2TokenCustomizer` maps a user's claims from an authentication provider to the `id_token` produced by Spring Authorization Server:
.`FederatedIdentityIdTokenCustomizer`
[source,java]
----
include::{samples-dir}/demo-authorizationserver/src/main/java/sample/federation/FederatedIdentityIdTokenCustomizer.java[tags=imports;class]
----
You can configure Spring Authorization Server to use this customizer by publishing it as a `@Bean` as in the following example:
.Configure `FederatedIdentityIdTokenCustomizer`
[source,java]
----
@Bean
public OAuth2TokenCustomizer<JwtEncodingContext> idTokenCustomizer() {
return new FederatedIdentityIdTokenCustomizer();
}
----

View File

@@ -0,0 +1,102 @@
[[how-to-userinfo]]
= How-to: Customize the OpenID Connect 1.0 UserInfo response
:index-link: ../how-to.html
:docs-dir: ..
This guide shows how to customize the xref:protocol-endpoints.adoc#oidc-user-info-endpoint[UserInfo endpoint] of the xref:index.adoc[Spring Authorization Server].
The purpose of this guide is to demonstrate how to enable the endpoint and use the available customization options to produce a custom response.
* xref:guides/how-to-userinfo.adoc#enable-user-info[Enable the User Info Endpoint]
* xref:guides/how-to-userinfo.adoc#customize-user-info[Customize the User Info response]
[[enable-user-info]]
== Enable the User Info Endpoint
The xref:protocol-endpoints.adoc#oidc-user-info-endpoint[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].
> The Access Token obtained from an OpenID Connect Authentication Request MUST be sent as a Bearer Token, per Section 2 of https://openid.net/specs/openid-connect-core-1_0.html#RFC6750[OAuth 2.0 Bearer Token Usage] [RFC6750].
Before customizing the response, you need to enable the UserInfo endpoint.
The following listing shows how to enable the {spring-security-reference-base-url}/servlet/oauth2/resource-server/jwt.html[OAuth2 resource server configuration].
[[sample.userinfo]]
[source,java]
----
include::{examples-dir}/main/java/sample/userinfo/EnableUserInfoSecurityConfig.java[]
----
TIP: Click on the "Expand folded text" icon in the code sample above to display the full example.
This configuration provides the following:
<1> A Spring Security filter chain for the xref:{docs-dir}/protocol-endpoints.adoc[Protocol Endpoints].
<2> Resource server support that allows User Info requests to be authenticated with access tokens.
<3> An instance of `JwtDecoder` used to validate access tokens.
[[customize-user-info]]
== Customize the User Info response
The following sections describe some options for customizing the user info response.
* xref:guides/how-to-userinfo.adoc#customize-id-token[Customize the ID Token]
* xref:guides/how-to-userinfo.adoc#customize-user-info-mapper[Customize the User Info Mapper]
[[customize-id-token]]
=== Customize the ID Token
By default, the user info response is generated by using claims from the `id_token` that are returned with the xref:protocol-endpoints.adoc#oauth2-token-endpoint[token response].
Using the default strategy, https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims[standard claims] are returned only with the user info response based on the https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims[requested scopes] during authorization.
The preferred way to customize the user info response is to add standard claims to the `id_token`.
The following listing shows how to add claims to the `id_token`.
[[sample.userinfo.idtoken]]
[source,java]
----
include::{examples-dir}/main/java/sample/userinfo/idtoken/IdTokenCustomizerConfig.java[]
----
This configuration provides the following:
<1> An instance of xref:core-model-components.adoc#oauth2-token-customizer[`OAuth2TokenCustomizer`] for customizing the `id_token`.
<2> A custom service used to obtain user info in a domain-specific way.
The following listing shows a custom service for looking up user info in a domain-specific way:
[source,java]
----
include::{examples-dir}/main/java/sample/userinfo/idtoken/OidcUserInfoService.java[]
----
[[customize-user-info-mapper]]
=== Customize the User Info Mapper
To fully customize the user info response, you can provide a custom user info mapper capable of generating the object used to render the response, which is an instance of the `OidcUserInfo` class from Spring Security.
The mapper implementation receives an instance of `OidcUserInfoAuthenticationContext` with information about the current request, including the xref:core-model-components.adoc#oauth2-authorization[`OAuth2Authorization`].
The following listing shows how to use the customization option that is available while working directly with the `OAuth2AuthorizationServerConfigurer`.
[[sample.userinfo.jwt]]
[source,java]
----
include::{examples-dir}/main/java/sample/userinfo/jwt/JwtUserInfoMapperSecurityConfig.java[]
----
This configuration maps claims from the access token (which is a JWT when using the xref:getting-started.adoc#sample.gettingStarted[Getting Started config]) to populate the user info response and provides the following:
<1> A Spring Security filter chain for the xref:{docs-dir}/protocol-endpoints.adoc[Protocol Endpoints].
<2> A user info mapper that maps claims in a domain-specific way.
<3> An example showing the configuration option for customizing the user info mapper.
<4> Resource server support that allows User Info requests to be authenticated with access tokens.
<5> An example showing how to apply the `OAuth2AuthorizationServerConfigurer` to the Spring Security configuration.
The user info mapper is not limited to mapping claims from a JWT, but this is a simple example that demonstrates the customization option.
Similar to the xref:guides/how-to-userinfo.adoc#customize-id-token[example shown earlier] where we customize claims of the ID token, you can customize claims of the access token itself ahead of time, as in the following example:
[source,java]
----
include::{examples-dir}/main/java/sample/userinfo/jwt/JwtTokenCustomizerConfig.java[]
----
Whether you customize the user info response directly or use this example and customize the access token, you can look up information in a database, perform an LDAP query, make a request to another service, or use any other means of obtaining the information you want to be presented in the user info response.

View File

@@ -0,0 +1,13 @@
[[how-to]]
= How-to Guides
:page-section-summary-toc: 1
[[how-to-overview]]
== List of Guides
* xref:guides/how-to-pkce.adoc[Authenticate using a Single Page Application with PKCE]
* xref:guides/how-to-social-login.adoc[Authenticate using Social Login]
* xref:guides/how-to-ext-grant-type.adoc[Implement an Extension Authorization Grant Type]
* xref:guides/how-to-userinfo.adoc[Customize the OpenID Connect 1.0 UserInfo response]
* xref:guides/how-to-jpa.adoc[Implement core services with JPA]

View File

@@ -0,0 +1,109 @@
[[top]]
= Overview
:page-section-summary-toc: 1
Joe Grandja, Steve Riesenberg
v{spring-authorization-server-version}
:docinfo: private-footer
:nofooter:
This site contains reference documentation and how-to guides for Spring Authorization Server.
[horizontal]
xref:index.adoc#introducing-spring-authorization-server[Introduction] :: Introduction and feature list
xref:getting-help.adoc[Getting Help] :: Links to samples, questions and issues
xref:getting-started.adoc[Getting Started] :: System requirements, dependencies and developing your first application
xref:configuration-model.adoc[Configuration Model] :: Default configuration and customizing the configuration
xref:core-model-components.adoc[Core Model / Components] :: Core domain model and component interfaces
xref:protocol-endpoints.adoc[Protocol Endpoints] :: OAuth2 and OpenID Connect 1.0 protocol endpoint implementations
xref:how-to.adoc[How-to Guides] :: Guides to get the most from Spring Authorization Server
[[introducing-spring-authorization-server]]
== Introducing Spring Authorization Server
Spring Authorization Server is a framework that provides implementations of the https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-07[OAuth 2.1] and https://openid.net/specs/openid-connect-core-1_0.html[OpenID Connect 1.0] specifications and other related specifications.
It is built on top of https://spring.io/projects/spring-security[Spring Security] to provide a secure, light-weight, and customizable foundation for building OpenID Connect 1.0 Identity Providers and OAuth2 Authorization Server products.
[[feature-list]]
== Feature List
Spring Authorization Server supports the following features:
[cols="2a,4a,6a"]
|===
|Category |Feature |Related specifications
|xref:protocol-endpoints.adoc#oauth2-token-endpoint[Authorization Grant]
|
* Authorization Code
** xref:protocol-endpoints.adoc#oauth2-authorization-endpoint[User Consent]
* Client Credentials
* Refresh Token
* Device Code
** xref:protocol-endpoints.adoc#oauth2-device-verification-endpoint[User Consent]
|
* The OAuth 2.1 Authorization Framework (https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-07[draft])
** https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-07#section-4.1[Authorization Code Grant]
** https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-07#section-4.2[Client Credentials Grant]
** https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-07#section-4.3[Refresh Token Grant]
* OpenID Connect Core 1.0 (https://openid.net/specs/openid-connect-core-1_0.html[spec])
** https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth[Authorization Code Flow]
* OAuth 2.0 Device Authorization Grant
(https://tools.ietf.org/html/rfc8628[spec])
** https://tools.ietf.org/html/rfc8628#section-3[Device Flow]
|xref:core-model-components.adoc#oauth2-token-generator[Token Formats]
|
* Self-contained (JWT)
* Reference (Opaque)
|
* JSON Web Token (JWT) (https://tools.ietf.org/html/rfc7519[RFC 7519])
* JSON Web Signature (JWS) (https://tools.ietf.org/html/rfc7515[RFC 7515])
|xref:configuration-model.adoc#configuring-client-authentication[Client Authentication]
|
* `client_secret_basic`
* `client_secret_post`
* `client_secret_jwt`
* `private_key_jwt`
* `none` (public clients)
|
* The OAuth 2.1 Authorization Framework (https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-07#section-2.4[Client Authentication])
* JSON Web Token (JWT) Profile for OAuth 2.0 Client Authentication (https://tools.ietf.org/html/rfc7523[RFC 7523])
* Proof Key for Code Exchange by OAuth Public Clients (PKCE) (https://tools.ietf.org/html/rfc7636[RFC 7636])
|xref:protocol-endpoints.adoc[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]
* 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]
* xref:protocol-endpoints.adoc#oidc-client-registration-endpoint[OpenID Connect 1.0 Client Registration Endpoint]
|
* The OAuth 2.1 Authorization Framework (https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-07[draft])
** https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-07#section-3.1[Authorization Endpoint]
** https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-07#section-3.2[Token Endpoint]
* OAuth 2.0 Device Authorization Grant (https://tools.ietf.org/html/rfc8628[RFC 8628])
** https://tools.ietf.org/html/rfc8628#section-3.1[Device Authorization Endpoint]
** 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 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])
** https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig[Provider Configuration Endpoint]
* OpenID Connect RP-Initiated Logout 1.0 (https://openid.net/specs/openid-connect-rpinitiated-1_0.html[spec])
** https://openid.net/specs/openid-connect-rpinitiated-1_0.html#RPLogout[Logout Endpoint]
* OpenID Connect Core 1.0 (https://openid.net/specs/openid-connect-core-1_0.html[spec])
** https://openid.net/specs/openid-connect-core-1_0.html#UserInfo[UserInfo Endpoint]
* OpenID Connect Dynamic Client Registration 1.0 (https://openid.net/specs/openid-connect-registration-1_0.html[spec])
** https://openid.net/specs/openid-connect-registration-1_0.html#ClientRegistration[Client Registration Endpoint]
** https://openid.net/specs/openid-connect-registration-1_0.html#ClientConfigurationEndpoint[Client Configuration Endpoint]
|===

View File

@@ -0,0 +1,665 @@
[[protocol-endpoints]]
= Protocol Endpoints
[[oauth2-authorization-endpoint]]
== OAuth2 Authorization Endpoint
`OAuth2AuthorizationEndpointConfigurer` provides the ability to customize the https://datatracker.ietf.org/doc/html/rfc6749#section-3.1[OAuth2 Authorization 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/rfc6749#section-4.1.1[OAuth2 authorization requests].
`OAuth2AuthorizationEndpointConfigurer` provides the following configuration options:
[source,java]
----
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
authorizationServerConfigurer
.authorizationEndpoint(authorizationEndpoint ->
authorizationEndpoint
.authorizationRequestConverter(authorizationRequestConverter) <1>
.authorizationRequestConverters(authorizationRequestConvertersConsumer) <2>
.authenticationProvider(authenticationProvider) <3>
.authenticationProviders(authenticationProvidersConsumer) <4>
.authorizationResponseHandler(authorizationResponseHandler) <5>
.errorResponseHandler(errorResponseHandler) <6>
.consentPage("/oauth2/v1/authorize") <7>
);
return http.build();
}
----
<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`.
<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`.
<3> `authenticationProvider()`: Adds an `AuthenticationProvider` (_main processor_) used for authenticating the `OAuth2AuthorizationCodeRequestAuthenticationToken` or `OAuth2AuthorizationConsentAuthenticationToken`.
<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> `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].
<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].
<7> `consentPage()`: The `URI` of the custom consent page to redirect resource owners to if consent is required during the authorization request flow.
`OAuth2AuthorizationEndpointConfigurer` configures the `OAuth2AuthorizationEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
`OAuth2AuthorizationEndpointFilter` is the `Filter` that processes OAuth2 authorization requests (and consents).
`OAuth2AuthorizationEndpointFilter` is configured with the following defaults:
* `*AuthenticationConverter*` -- A `DelegatingAuthenticationConverter` composed of `OAuth2AuthorizationCodeRequestAuthenticationConverter` and `OAuth2AuthorizationConsentAuthenticationConverter`.
* `*AuthenticationManager*` -- An `AuthenticationManager` composed of `OAuth2AuthorizationCodeRequestAuthenticationProvider` and `OAuth2AuthorizationConsentAuthenticationProvider`.
* `*AuthenticationSuccessHandler*` -- An internal implementation that handles an "`authenticated`" `OAuth2AuthorizationCodeRequestAuthenticationToken` and returns the `OAuth2AuthorizationResponse`.
* `*AuthenticationFailureHandler*` -- An internal implementation that uses the `OAuth2Error` associated with the `OAuth2AuthorizationCodeRequestAuthenticationException` and returns the `OAuth2Error` response.
[[oauth2-authorization-endpoint-customizing-authorization-request-validation]]
=== Customizing Authorization Request Validation
`OAuth2AuthorizationCodeRequestAuthenticationValidator` is the default validator used for validating specific OAuth2 authorization request parameters used in the Authorization Code Grant.
The default implementation validates the `redirect_uri` and `scope` parameters.
If validation fails, an `OAuth2AuthorizationCodeRequestAuthenticationException` is thrown.
`OAuth2AuthorizationCodeRequestAuthenticationProvider` provides the ability to override the default authorization request validation by supplying a custom authentication validator of type `Consumer<OAuth2AuthorizationCodeRequestAuthenticationContext>` to `setAuthenticationValidator()`.
[TIP]
`OAuth2AuthorizationCodeRequestAuthenticationContext` holds the `OAuth2AuthorizationCodeRequestAuthenticationToken`, which contains the OAuth2 authorization request parameters.
[IMPORTANT]
If validation fails, the authentication validator *MUST* throw `OAuth2AuthorizationCodeRequestAuthenticationException`.
A common use case during the development life cycle phase is to allow for `localhost` in the `redirect_uri` parameter.
The following example shows how to configure `OAuth2AuthorizationCodeRequestAuthenticationProvider` with a custom authentication validator that allows for `localhost` in the `redirect_uri` parameter:
[source,java]
----
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
authorizationServerConfigurer
.authorizationEndpoint(authorizationEndpoint ->
authorizationEndpoint
.authenticationProviders(configureAuthenticationValidator())
);
return http.build();
}
private Consumer<List<AuthenticationProvider>> configureAuthenticationValidator() {
return (authenticationProviders) ->
authenticationProviders.forEach((authenticationProvider) -> {
if (authenticationProvider instanceof OAuth2AuthorizationCodeRequestAuthenticationProvider) {
Consumer<OAuth2AuthorizationCodeRequestAuthenticationContext> authenticationValidator =
// Override default redirect_uri validator
new CustomRedirectUriValidator()
// Reuse default scope validator
.andThen(OAuth2AuthorizationCodeRequestAuthenticationValidator.DEFAULT_SCOPE_VALIDATOR);
((OAuth2AuthorizationCodeRequestAuthenticationProvider) authenticationProvider)
.setAuthenticationValidator(authenticationValidator);
}
});
}
static class CustomRedirectUriValidator implements Consumer<OAuth2AuthorizationCodeRequestAuthenticationContext> {
@Override
public void accept(OAuth2AuthorizationCodeRequestAuthenticationContext authenticationContext) {
OAuth2AuthorizationCodeRequestAuthenticationToken authorizationCodeRequestAuthentication =
authenticationContext.getAuthentication();
RegisteredClient registeredClient = authenticationContext.getRegisteredClient();
String requestedRedirectUri = authorizationCodeRequestAuthentication.getRedirectUri();
// Use exact string matching when comparing client redirect URIs against pre-registered URIs
if (!registeredClient.getRedirectUris().contains(requestedRedirectUri)) {
OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST);
throw new OAuth2AuthorizationCodeRequestAuthenticationException(error, null);
}
}
}
----
[[oauth2-device-authorization-endpoint]]
== OAuth2 Device Authorization Endpoint
`OAuth2DeviceAuthorizationEndpointConfigurer` provides the ability to customize the https://datatracker.ietf.org/doc/html/rfc8628#section-3.1[OAuth2 Device Authorization endpoint].
It defines extension points that let you customize the pre-processing, main processing, and post-processing logic for OAuth2 device authorization requests.
`OAuth2DeviceAuthorizationEndpointConfigurer` provides the following configuration options:
[source,java]
----
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
authorizationServerConfigurer
.deviceAuthorizationEndpoint(deviceAuthorizationEndpoint ->
deviceAuthorizationEndpoint
.deviceAuthorizationRequestConverter(deviceAuthorizationRequestConverter) <1>
.deviceAuthorizationRequestConverters(deviceAuthorizationRequestConvertersConsumer) <2>
.authenticationProvider(authenticationProvider) <3>
.authenticationProviders(authenticationProvidersConsumer) <4>
.deviceAuthorizationResponseHandler(deviceAuthorizationResponseHandler) <5>
.errorResponseHandler(errorResponseHandler) <6>
.verificationUri("/oauth2/v1/device_verification") <7>
);
return http.build();
}
----
<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`.
<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`.
<3> `authenticationProvider()`: Adds an `AuthenticationProvider` (_main processor_) used for authenticating the `OAuth2DeviceAuthorizationRequestAuthenticationToken`.
<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> `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].
<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].
<7> `verificationUri()`: The `URI` of the custom end-user verification page to direct resource owners to on a secondary device.
`OAuth2DeviceAuthorizationEndpointConfigurer` configures the `OAuth2DeviceAuthorizationEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
`OAuth2DeviceAuthorizationEndpointFilter` is the `Filter` that processes OAuth2 device authorization requests.
`OAuth2DeviceAuthorizationEndpointFilter` is configured with the following defaults:
* `*AuthenticationConverter*` -- An `OAuth2DeviceAuthorizationRequestAuthenticationConverter`.
* `*AuthenticationManager*` -- An `AuthenticationManager` composed of `OAuth2DeviceAuthorizationRequestAuthenticationProvider`.
* `*AuthenticationSuccessHandler*` -- An internal implementation that handles an "`authenticated`" `OAuth2DeviceAuthorizationRequestAuthenticationToken` and returns the `OAuth2DeviceAuthorizationResponse`.
* `*AuthenticationFailureHandler*` -- An internal implementation that uses the `OAuth2Error` associated with the `OAuth2AuthenticationException` and returns the `OAuth2Error` response.
[[oauth2-device-verification-endpoint]]
== OAuth2 Device Verification Endpoint
`OAuth2DeviceVerificationEndpointConfigurer` provides the ability to customize the https://datatracker.ietf.org/doc/html/rfc8628#section-3.3[OAuth2 Device Verification endpoint] (or "User Interaction").
It defines extension points that let you customize the pre-processing, main processing, and post-processing logic for OAuth2 device verification requests.
`OAuth2DeviceVerificationEndpointConfigurer` provides the following configuration options:
[source,java]
----
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
authorizationServerConfigurer
.deviceVerificationEndpoint(deviceVerificationEndpoint ->
deviceVerificationEndpoint
.deviceVerificationRequestConverter(deviceVerificationRequestConverter) <1>
.deviceVerificationRequestConverters(deviceVerificationRequestConvertersConsumer) <2>
.authenticationProvider(authenticationProvider) <3>
.authenticationProviders(authenticationProvidersConsumer) <4>
.deviceVerificationResponseHandler(deviceVerificationResponseHandler) <5>
.errorResponseHandler(errorResponseHandler) <6>
.consentPage("/oauth2/v1/consent") <7>
);
return http.build();
}
----
<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`.
<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`.
<3> `authenticationProvider()`: Adds an `AuthenticationProvider` (_main processor_) used for authenticating the `OAuth2DeviceVerificationAuthenticationToken` or `OAuth2DeviceAuthorizationConsentAuthenticationToken`.
<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> `deviceVerificationResponseHandler()`: The `AuthenticationSuccessHandler` (_post-processor_) used for handling an "`authenticated`" `OAuth2DeviceVerificationAuthenticationToken` and directing the resource owner to return to their device.
<6> `errorResponseHandler()`: The `AuthenticationFailureHandler` (_post-processor_) used for handling an `OAuth2AuthenticationException` and returning the error response.
<7> `consentPage()`: The `URI` of the custom consent page to redirect resource owners to if consent is required during the device verification request flow.
`OAuth2DeviceVerificationEndpointConfigurer` configures the `OAuth2DeviceVerificationEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
`OAuth2DeviceVerificationEndpointFilter` is the `Filter` that processes OAuth2 device verification requests (and consents).
`OAuth2DeviceVerificationEndpointFilter` is configured with the following defaults:
* `*AuthenticationConverter*` -- A `DelegatingAuthenticationConverter` composed of `OAuth2DeviceVerificationAuthenticationConverter` and `OAuth2DeviceAuthorizationConsentAuthenticationConverter`.
* `*AuthenticationManager*` -- An `AuthenticationManager` composed of `OAuth2DeviceVerificationAuthenticationProvider` and `OAuth2DeviceAuthorizationConsentAuthenticationProvider`.
* `*AuthenticationSuccessHandler*` -- A `SimpleUrlAuthenticationSuccessHandler` that handles an "`authenticated`" `OAuth2DeviceVerificationAuthenticationToken` and redirects the user to a success page (`/?success`).
* `*AuthenticationFailureHandler*` -- An internal implementation that uses the `OAuth2Error` associated with the `OAuth2AuthenticationException` and returns the `OAuth2Error` response.
[[oauth2-token-endpoint]]
== OAuth2 Token Endpoint
`OAuth2TokenEndpointConfigurer` provides the ability to customize the https://datatracker.ietf.org/doc/html/rfc6749#section-3.2[OAuth2 Token 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/rfc6749#section-4.1.3[OAuth2 access token requests].
`OAuth2TokenEndpointConfigurer` provides the following configuration options:
[source,java]
----
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
authorizationServerConfigurer
.tokenEndpoint(tokenEndpoint ->
tokenEndpoint
.accessTokenRequestConverter(accessTokenRequestConverter) <1>
.accessTokenRequestConverters(accessTokenRequestConvertersConsumer) <2>
.authenticationProvider(authenticationProvider) <3>
.authenticationProviders(authenticationProvidersConsumer) <4>
.accessTokenResponseHandler(accessTokenResponseHandler) <5>
.errorResponseHandler(errorResponseHandler) <6>
);
return http.build();
}
----
<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`.
<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`.
<3> `authenticationProvider()`: Adds an `AuthenticationProvider` (_main processor_) used for authenticating the `OAuth2AuthorizationGrantAuthenticationToken`.
<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> `accessTokenResponseHandler()`: The `AuthenticationSuccessHandler` (_post-processor_) used for handling an `OAuth2AccessTokenAuthenticationToken` and returning the https://datatracker.ietf.org/doc/html/rfc6749#section-5.1[`OAuth2AccessTokenResponse`].
<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].
`OAuth2TokenEndpointConfigurer` configures the `OAuth2TokenEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
`OAuth2TokenEndpointFilter` is the `Filter` that processes OAuth2 access token requests.
The supported https://datatracker.ietf.org/doc/html/rfc6749#section-1.3[authorization grant types] are `authorization_code`, `refresh_token`, `client_credentials`, and `urn:ietf:params:oauth:grant-type:device_code`.
`OAuth2TokenEndpointFilter` is configured with the following defaults:
* `*AuthenticationConverter*` -- A `DelegatingAuthenticationConverter` composed of `OAuth2AuthorizationCodeAuthenticationConverter`, `OAuth2RefreshTokenAuthenticationConverter`, `OAuth2ClientCredentialsAuthenticationConverter`, and `OAuth2DeviceCodeAuthenticationConverter`.
* `*AuthenticationManager*` -- An `AuthenticationManager` composed of `OAuth2AuthorizationCodeAuthenticationProvider`, `OAuth2RefreshTokenAuthenticationProvider`, `OAuth2ClientCredentialsAuthenticationProvider`, and `OAuth2DeviceCodeAuthenticationProvider`.
* `*AuthenticationSuccessHandler*` -- An internal implementation that handles an `OAuth2AccessTokenAuthenticationToken` and returns the `OAuth2AccessTokenResponse`.
* `*AuthenticationFailureHandler*` -- An internal implementation that uses the `OAuth2Error` associated with the `OAuth2AuthenticationException` and returns the `OAuth2Error` response.
[[oauth2-token-introspection-endpoint]]
== OAuth2 Token Introspection Endpoint
`OAuth2TokenIntrospectionEndpointConfigurer` provides the ability to customize the https://datatracker.ietf.org/doc/html/rfc7662#section-2[OAuth2 Token Introspection 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/rfc7662#section-2.1[OAuth2 introspection requests].
`OAuth2TokenIntrospectionEndpointConfigurer` provides the following configuration options:
[source,java]
----
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
authorizationServerConfigurer
.tokenIntrospectionEndpoint(tokenIntrospectionEndpoint ->
tokenIntrospectionEndpoint
.introspectionRequestConverter(introspectionRequestConverter) <1>
.introspectionRequestConverters(introspectionRequestConvertersConsumer) <2>
.authenticationProvider(authenticationProvider) <3>
.authenticationProviders(authenticationProvidersConsumer) <4>
.introspectionResponseHandler(introspectionResponseHandler) <5>
.errorResponseHandler(errorResponseHandler) <6>
);
return http.build();
}
----
<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`.
<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`.
<3> `authenticationProvider()`: Adds an `AuthenticationProvider` (_main processor_) used for authenticating the `OAuth2TokenIntrospectionAuthenticationToken`.
<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> `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].
<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].
`OAuth2TokenIntrospectionEndpointConfigurer` configures the `OAuth2TokenIntrospectionEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
`OAuth2TokenIntrospectionEndpointFilter` is the `Filter` that processes OAuth2 introspection requests.
`OAuth2TokenIntrospectionEndpointFilter` is configured with the following defaults:
* `*AuthenticationConverter*` -- An `OAuth2TokenIntrospectionAuthenticationConverter`.
* `*AuthenticationManager*` -- An `AuthenticationManager` composed of `OAuth2TokenIntrospectionAuthenticationProvider`.
* `*AuthenticationSuccessHandler*` -- An internal implementation that handles an "`authenticated`" `OAuth2TokenIntrospectionAuthenticationToken` and returns the `OAuth2TokenIntrospection` response.
* `*AuthenticationFailureHandler*` -- An internal implementation that uses the `OAuth2Error` associated with the `OAuth2AuthenticationException` and returns the `OAuth2Error` response.
[[oauth2-token-revocation-endpoint]]
== OAuth2 Token Revocation Endpoint
`OAuth2TokenRevocationEndpointConfigurer` provides the ability to customize the https://datatracker.ietf.org/doc/html/rfc7009#section-2[OAuth2 Token Revocation 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/rfc7009#section-2.1[OAuth2 revocation requests].
`OAuth2TokenRevocationEndpointConfigurer` provides the following configuration options:
[source,java]
----
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
authorizationServerConfigurer
.tokenRevocationEndpoint(tokenRevocationEndpoint ->
tokenRevocationEndpoint
.revocationRequestConverter(revocationRequestConverter) <1>
.revocationRequestConverters(revocationRequestConvertersConsumer) <2>
.authenticationProvider(authenticationProvider) <3>
.authenticationProviders(authenticationProvidersConsumer) <4>
.revocationResponseHandler(revocationResponseHandler) <5>
.errorResponseHandler(errorResponseHandler) <6>
);
return http.build();
}
----
<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`.
<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`.
<3> `authenticationProvider()`: Adds an `AuthenticationProvider` (_main processor_) used for authenticating the `OAuth2TokenRevocationAuthenticationToken`.
<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> `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].
<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].
`OAuth2TokenRevocationEndpointConfigurer` configures the `OAuth2TokenRevocationEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
`OAuth2TokenRevocationEndpointFilter` is the `Filter` that processes OAuth2 revocation requests.
`OAuth2TokenRevocationEndpointFilter` is configured with the following defaults:
* `*AuthenticationConverter*` -- An `OAuth2TokenRevocationAuthenticationConverter`.
* `*AuthenticationManager*` -- An `AuthenticationManager` composed of `OAuth2TokenRevocationAuthenticationProvider`.
* `*AuthenticationSuccessHandler*` -- An internal implementation that handles an "`authenticated`" `OAuth2TokenRevocationAuthenticationToken` and returns the OAuth2 revocation response.
* `*AuthenticationFailureHandler*` -- An internal implementation that uses the `OAuth2Error` associated with the `OAuth2AuthenticationException` and returns the `OAuth2Error` response.
[[oauth2-authorization-server-metadata-endpoint]]
== OAuth2 Authorization Server Metadata Endpoint
`OAuth2AuthorizationServerMetadataEndpointConfigurer` provides the ability to customize the https://datatracker.ietf.org/doc/html/rfc8414#section-3[OAuth2 Authorization Server Metadata endpoint].
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].
`OAuth2AuthorizationServerMetadataEndpointConfigurer` provides the following configuration option:
[source,java]
----
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
authorizationServerConfigurer
.authorizationServerMetadataEndpoint(authorizationServerMetadataEndpoint ->
authorizationServerMetadataEndpoint
.authorizationServerMetadataCustomizer(authorizationServerMetadataCustomizer)); <1>
return http.build();
}
----
<1> `authorizationServerMetadataCustomizer()`: The `Consumer` providing access to the `OAuth2AuthorizationServerMetadata.Builder` allowing the ability to customize the claims of the Authorization Server's configuration.
`OAuth2AuthorizationServerMetadataEndpointConfigurer` configures the `OAuth2AuthorizationServerMetadataEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
`OAuth2AuthorizationServerMetadataEndpointFilter` is the `Filter` that returns the https://datatracker.ietf.org/doc/html/rfc8414#section-3.2[OAuth2AuthorizationServerMetadata response].
[[jwk-set-endpoint]]
== JWK Set Endpoint
`OAuth2AuthorizationServerConfigurer` provides support for the https://datatracker.ietf.org/doc/html/rfc7517[JWK Set endpoint].
`OAuth2AuthorizationServerConfigurer` configures the `NimbusJwkSetEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
`NimbusJwkSetEndpointFilter` is the `Filter` that returns the https://datatracker.ietf.org/doc/html/rfc7517#section-5[JWK Set].
[NOTE]
The JWK Set endpoint is configured *only* if a `JWKSource<SecurityContext>` `@Bean` is registered.
[[oidc-provider-configuration-endpoint]]
== OpenID Connect 1.0 Provider Configuration Endpoint
`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].
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].
`OidcProviderConfigurationEndpointConfigurer` provides the following configuration option:
[source,java]
----
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
authorizationServerConfigurer
.oidc(oidc ->
oidc
.providerConfigurationEndpoint(providerConfigurationEndpoint ->
providerConfigurationEndpoint
.providerConfigurationCustomizer(providerConfigurationCustomizer) <1>
)
);
return http.build();
}
----
<1> `providerConfigurationCustomizer()`: The `Consumer` providing access to the `OidcProviderConfiguration.Builder` allowing the ability to customize the claims of the OpenID Provider's configuration.
`OidcProviderConfigurationEndpointConfigurer` configures the `OidcProviderConfigurationEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
`OidcProviderConfigurationEndpointFilter` is the `Filter` that returns the https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse[OidcProviderConfiguration response].
[[oidc-logout-endpoint]]
== OpenID Connect 1.0 Logout Endpoint
`OidcLogoutEndpointConfigurer` provides the ability to customize the https://openid.net/specs/openid-connect-rpinitiated-1_0.html#RPLogout[OpenID Connect 1.0 Logout endpoint].
It defines extension points that let you customize the pre-processing, main processing, and post-processing logic for RP-Initiated Logout requests.
`OidcLogoutEndpointConfigurer` provides the following configuration options:
[source,java]
----
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
authorizationServerConfigurer
.oidc(oidc ->
oidc
.logoutEndpoint(logoutEndpoint ->
logoutEndpoint
.logoutRequestConverter(logoutRequestConverter) <1>
.logoutRequestConverters(logoutRequestConvertersConsumer) <2>
.authenticationProvider(authenticationProvider) <3>
.authenticationProviders(authenticationProvidersConsumer) <4>
.logoutResponseHandler(logoutResponseHandler) <5>
.errorResponseHandler(errorResponseHandler) <6>
)
);
return http.build();
}
----
<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`.
<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`.
<3> `authenticationProvider()`: Adds an `AuthenticationProvider` (_main processor_) used for authenticating the `OidcLogoutAuthenticationToken`.
<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> `logoutResponseHandler()`: The `AuthenticationSuccessHandler` (_post-processor_) used for handling an "`authenticated`" `OidcLogoutAuthenticationToken` and performing the logout.
<6> `errorResponseHandler()`: The `AuthenticationFailureHandler` (_post-processor_) used for handling an `OAuth2AuthenticationException` and returning the error response.
`OidcLogoutEndpointConfigurer` configures the `OidcLogoutEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
`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.
`OidcLogoutEndpointFilter` is configured with the following defaults:
* `*AuthenticationConverter*` -- An `OidcLogoutAuthenticationConverter`.
* `*AuthenticationManager*` -- An `AuthenticationManager` composed of `OidcLogoutAuthenticationProvider`.
* `*AuthenticationSuccessHandler*` -- An internal implementation that handles an "`authenticated`" `OidcLogoutAuthenticationToken` and performs the logout.
* `*AuthenticationFailureHandler*` -- An internal implementation that uses the `OAuth2Error` associated with the `OAuth2AuthenticationException` and returns the `OAuth2Error` response.
[NOTE]
`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.
[TIP]
`OidcClientInitiatedLogoutSuccessHandler` is the corresponding configuration in Spring Securitys 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].
[[oidc-user-info-endpoint]]
== OpenID Connect 1.0 UserInfo Endpoint
`OidcUserInfoEndpointConfigurer` provides the ability to customize the https://openid.net/specs/openid-connect-core-1_0.html#UserInfo[OpenID Connect 1.0 UserInfo endpoint].
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].
`OidcUserInfoEndpointConfigurer` provides the following configuration options:
[source,java]
----
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
authorizationServerConfigurer
.oidc(oidc ->
oidc
.userInfoEndpoint(userInfoEndpoint ->
userInfoEndpoint
.userInfoRequestConverter(userInfoRequestConverter) <1>
.userInfoRequestConverters(userInfoRequestConvertersConsumer) <2>
.authenticationProvider(authenticationProvider) <3>
.authenticationProviders(authenticationProvidersConsumer) <4>
.userInfoResponseHandler(userInfoResponseHandler) <5>
.errorResponseHandler(errorResponseHandler) <6>
.userInfoMapper(userInfoMapper) <7>
)
);
return http.build();
}
----
<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`.
<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`.
<3> `authenticationProvider()`: Adds an `AuthenticationProvider` (_main processor_) used for authenticating the `OidcUserInfoAuthenticationToken`.
<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> `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].
<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].
<7> `userInfoMapper()`: The `Function` used to extract claims from `OidcUserInfoAuthenticationContext` to an instance of `OidcUserInfo`.
`OidcUserInfoEndpointConfigurer` configures the `OidcUserInfoEndpointFilter` and registers it with the OAuth2 authorization server `SecurityFilterChain` `@Bean`.
`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].
`OidcUserInfoEndpointFilter` is configured with the following defaults:
* `*AuthenticationConverter*` -- An internal implementation that obtains the `Authentication` from the `SecurityContext` and creates an `OidcUserInfoAuthenticationToken` with the principal.
* `*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.
* `*AuthenticationSuccessHandler*` -- An internal implementation that handles an "`authenticated`" `OidcUserInfoAuthenticationToken` and returns the `OidcUserInfo` response.
* `*AuthenticationFailureHandler*` -- An internal implementation that uses the `OAuth2Error` associated with the `OAuth2AuthenticationException` and returns the `OAuth2Error` response.
[TIP]
You can customize the ID Token by providing an xref:core-model-components.adoc#oauth2-token-customizer[`OAuth2TokenCustomizer<JwtEncodingContext>`] `@Bean`.
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].
The following example shows how to enable the OAuth2 resource server configuration:
[source,java]
----
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
...
http.oauth2ResourceServer(resourceServer -> resourceServer.jwt(Customizer.withDefaults()));
return http.build();
}
@Bean
public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
}
----
[NOTE]
A `JwtDecoder` `@Bean` is *REQUIRED* for the OpenID Connect 1.0 UserInfo endpoint.
[TIP]
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.
[[oidc-client-registration-endpoint]]
== OpenID Connect 1.0 Client Registration Endpoint
`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].
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].
`OidcClientRegistrationEndpointConfigurer` provides the following configuration options:
[source,java]
----
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
authorizationServerConfigurer
.oidc(oidc ->
oidc
.clientRegistrationEndpoint(clientRegistrationEndpoint ->
clientRegistrationEndpoint
.clientRegistrationRequestConverter(clientRegistrationRequestConverter) <1>
.clientRegistrationRequestConverters(clientRegistrationRequestConvertersConsumers) <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://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`.
<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 `OidcClientRegistrationAuthenticationToken`.
<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`" `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].
<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.
`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].
[TIP]
`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].
`OidcClientRegistrationEndpointFilter` is configured with the following defaults:
* `*AuthenticationConverter*` -- An `OidcClientRegistrationAuthenticationConverter`.
* `*AuthenticationManager*` -- An `AuthenticationManager` composed of `OidcClientRegistrationAuthenticationProvider` and `OidcClientConfigurationAuthenticationProvider`.
* `*AuthenticationSuccessHandler*` -- An internal implementation that handles an "`authenticated`" `OidcClientRegistrationAuthenticationToken` and returns the `OidcClientRegistration` response.
* `*AuthenticationFailureHandler*` -- An internal implementation that uses the `OAuth2Error` associated with the `OAuth2AuthenticationException` and returns the `OAuth2Error` response.
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.
[IMPORTANT]
The access token in a Client Registration request *REQUIRES* the OAuth2 scope `client.create`.
[IMPORTANT]
The access token in a Client Read request *REQUIRES* the OAuth2 scope `client.read`.
The following example shows how to enable the OAuth2 resource server configuration:
[source,java]
----
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
...
http.oauth2ResourceServer(resourceServer -> resourceServer.jwt(Customizer.withDefaults()));
return http.build();
}
@Bean
public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
}
----
[NOTE]
A `JwtDecoder` `@Bean` is *REQUIRED* for the OpenID Connect 1.0 Client Registration endpoint.