对于最新的稳定版本,请使用 Spring Authorization Server 1.4.0! |
配置模型
默认配置
OAuth2AuthorizationServerConfiguration
是为 OAuth2 授权服务器提供最低默认配置的 a。@Configuration
OAuth2AuthorizationServerConfiguration
使用 OAuth2AuthorizationServerConfigurer
应用默认配置,并注册一个由支持 OAuth2 授权服务器的所有基础设施组件组成的组件。SecurityFilterChain
@Bean
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(HttpSecurity) 是一种便捷的 () 实用程序方法,它将默认的 OAuth2 安全配置应用于 。static HttpSecurity |
OAuth2 授权服务器配置了以下默认协议端点:SecurityFilterChain
@Bean
仅当注册了 a 时,才会配置 JWK Set 端点。JWKSource<SecurityContext> @Bean |
以下示例显示如何使用 应用最小默认配置:OAuth2AuthorizationServerConfiguration
@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);
}
}
authorization_code授权要求资源所有者进行身份验证。因此,除了默认的 OAuth2 安全配置之外,还必须配置用户身份验证机制。 |
OpenID Connect 1.0 在默认配置中处于禁用状态。以下示例显示了如何通过初始化 OpenID Connect 1.0 来启用:OidcConfigurer
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
.oidc(Customizer.withDefaults()); // Initialize `OidcConfigurer`
return http.build();
}
除了默认协议端点之外,OAuth2 授权服务器还配置了以下 OpenID Connect 1.0 协议端点:SecurityFilterChain
@Bean
默认情况下,OpenID Connect 1.0 客户端注册终端节点处于禁用状态,因为许多部署不需要动态客户端注册。 |
OAuth2AuthorizationServerConfiguration.jwtDecoder(JWKSource<SecurityContext>) 是一种方便的 () 实用程序方法,可用于注册 ,对于 OpenID Connect 1.0 UserInfo 端点和 OpenID Connect 1.0 客户端注册端点是必需的。static JwtDecoder @Bean |
以下示例说明如何注册 :JwtDecoder
@Bean
@Bean
public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
}
的主要目的是提供一种方便的方法来为 OAuth2 授权服务器应用最低默认配置。但是,在大多数情况下,需要自定义配置。OAuth2AuthorizationServerConfiguration
自定义配置
OAuth2AuthorizationServerConfigurer
提供完全自定义 OAuth2 授权服务器安全配置的能力。
它允许您指定要使用的核心组件 - 例如,RegisteredClientRepository
、OAuth2AuthorizationService
、OAuth2TokenGenerator
等。
此外,它还允许您自定义协议终端节点的请求处理逻辑,例如,授权终端节点、设备授权终端节点、设备验证终端节点、令牌终端节点、令牌自检终端节点等。
OAuth2AuthorizationServerConfigurer
提供以下配置选项:
@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() :用于管理新客户端和现有客户端的 RegisteredClientRepository (REQUIRED)。 |
2 | authorizationService() :用于管理新授权和现有授权的 OAuth2AuthorizationService 。 |
3 | authorizationConsentService() :OAuth2AuthorizationConsentService ,用于管理新的和现有的授权同意。 |
4 | authorizationServerSettings() :用于自定义 OAuth2 授权服务器的配置设置的 AuthorizationServerSettings (REQUIRED)。 |
5 | tokenGenerator() :OAuth2TokenGenerator ,用于生成 OAuth2 授权服务器支持的令牌。 |
6 | clientAuthentication() :OAuth2 客户端身份验证的配置器。 |
7 | authorizationEndpoint() :OAuth2 授权端点的配置器。 |
8 | deviceAuthorizationEndpoint() :OAuth2 设备授权端点的配置器。 |
9 | deviceVerificationEndpoint() :OAuth2 Device Verification 端点的配置器。 |
10 | tokenEndpoint() :OAuth2 令牌端点的配置器。 |
11 | tokenIntrospectionEndpoint() :OAuth2 令牌自省端点的配置器。 |
12 | tokenRevocationEndpoint() :OAuth2 令牌吊销端点的配置器。 |
13 | authorizationServerMetadataEndpoint() :OAuth2 授权服务器元数据端点的配置器。 |
14 | providerConfigurationEndpoint() :OpenID Connect 1.0 提供程序配置终端节点的配置器。 |
15 | logoutEndpoint() :OpenID Connect 1.0 注销端点的配置器。 |
16 | userInfoEndpoint() :OpenID Connect 1.0 UserInfo 端点的配置器。 |
17 | clientRegistrationEndpoint() :OpenID Connect 1.0 客户端注册终端节点的配置器。 |
配置 Authorization Server 设置
AuthorizationServerSettings
包含 OAuth2 授权服务器的配置设置。
它指定协议端点以及颁发者标识符。
协议终端节点的默认值如下:URI
URI
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");
}
...
}
AuthorizationServerSettings 是 REQUIRED 组件。 |
@Import(OAuth2AuthorizationServerConfiguration.class) 会自动注册一个 (如果尚未提供)。AuthorizationServerSettings @Bean |
以下示例显示如何自定义配置设置并注册 :AuthorizationServerSettings
@Bean
@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();
}
它是一个上下文对象,用于保存 Authorization Server 运行时环境的信息。
它提供对 和 “current” issuer 标识符的访问。AuthorizationServerContext
AuthorizationServerSettings
如果未在 中配置颁发者标识符,则会从当前请求中解析该标识符。AuthorizationServerSettings.builder().issuer(String) |
可通过 访问,后者使用 将其与当前请求线程相关联。AuthorizationServerContext AuthorizationServerContextHolder ThreadLocal |
配置客户端身份验证
OAuth2ClientAuthenticationConfigurer
提供自定义 OAuth2 客户端身份验证的功能。
它定义了扩展点,允许您自定义客户端身份验证请求的预处理、主处理和后处理逻辑。
OAuth2ClientAuthenticationConfigurer
提供以下配置选项:
@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() :添加尝试从 中提取客户端凭据到 实例时使用的(预处理器)。AuthenticationConverter HttpServletRequest OAuth2ClientAuthenticationToken |
2 | authenticationConverters() :设置对 default 和(可选)added 的 提供访问权限,以允许添加、删除或自定义特定 .Consumer List AuthenticationConverter AuthenticationConverter |
3 | authenticationProvider() :添加一个(主处理器)用于验证 .AuthenticationProvider OAuth2ClientAuthenticationToken |
4 | authenticationProviders() :设置对 default 和(可选)added 的 提供访问权限,以允许添加、删除或自定义特定 .Consumer List AuthenticationProvider AuthenticationProvider |
5 | authenticationSuccessHandler() :用于处理成功的客户端身份验证并将 关联到 的(后处理器)。AuthenticationSuccessHandler OAuth2ClientAuthenticationToken SecurityContext |
6 | errorResponseHandler() :用于处理失败的客户端身份验证并返回 OAuth2Error 响应的(后处理器)。AuthenticationFailureHandler |
OAuth2ClientAuthenticationConfigurer
配置 并将其注册到 OAuth2 授权服务器 。 是处理客户端身份验证请求的 。OAuth2ClientAuthenticationFilter
SecurityFilterChain
@Bean
OAuth2ClientAuthenticationFilter
Filter
默认情况下,OAuth2 令牌端点、OAuth2 令牌自检端点和 OAuth2 令牌吊销端点需要客户端身份验证。
支持的客户端身份验证方法包括 、 和 (公共客户端)。client_secret_basic
client_secret_post
private_key_jwt
client_secret_jwt
tls_client_auth
self_signed_tls_client_auth
none
OAuth2ClientAuthenticationFilter
配置了以下默认值:
-
AuthenticationConverter
— A 由 、 、 、 和 组成。DelegatingAuthenticationConverter
JwtClientAssertionAuthenticationConverter
X509ClientCertificateAuthenticationConverter
ClientSecretBasicAuthenticationConverter
ClientSecretPostAuthenticationConverter
PublicClientAuthenticationConverter
-
AuthenticationManager
— 由 、 、 和 组成的 。AuthenticationManager
JwtClientAssertionAuthenticationProvider
X509ClientCertificateAuthenticationProvider
ClientSecretAuthenticationProvider
PublicClientAuthenticationProvider
-
AuthenticationSuccessHandler
— 将 “authenticated” (当前) 与 关联的内部实现。OAuth2ClientAuthenticationToken
Authentication
SecurityContext
-
AuthenticationFailureHandler
— 一种内部实现,它使用与 关联的 来返回 OAuth2 错误响应。OAuth2Error
OAuth2AuthenticationException
自定义 Jwt 客户端断言验证
JwtClientAssertionDecoderFactory.DEFAULT_JWT_VALIDATOR_FACTORY
是为指定 提供 的默认工厂,用于验证客户端断言的 、 、 和 声明。OAuth2TokenValidator<Jwt>
RegisteredClient
iss
sub
aud
exp
nbf
Jwt
JwtClientAssertionDecoderFactory
通过向 提供 类型的自定义工厂来覆盖默认客户端断言验证的功能。Jwt
Function<RegisteredClient, OAuth2TokenValidator<Jwt>>
setJwtValidatorFactory()
JwtClientAssertionDecoderFactory 是默认使用的,它为指定提供 ,并用于在 OAuth2 客户端身份验证期间验证 Bearer Token。JwtDecoderFactory JwtClientAssertionAuthenticationProvider JwtDecoder RegisteredClient Jwt |
自定义的一个常见用例是验证客户端断言中的其他声明。JwtClientAssertionDecoderFactory
Jwt
以下示例显示如何使用自定义进行配置,以验证客户端断言中的其他声明:JwtClientAssertionAuthenticationProvider
JwtClientAssertionDecoderFactory
Jwt
@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);
}
});
}
自定义 Mutual-TLS 客户端验证
X509ClientCertificateAuthenticationProvider
用于验证在 OAuth2 客户端验证期间使用或方法时收到的客户端链。
它还由“证书验证程序”组成,用于在 TLS 握手成功完成后验证客户端的内容。X509Certificate
ClientAuthenticationMethod.TLS_CLIENT_AUTH
ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH
X509Certificate
PKI 互助 TLS 方法
对于 PKI Mutual-TLS () 方法,证书验证程序的默认实现会根据设置 验证客户端的使用者可分辨名称。ClientAuthenticationMethod.TLS_CLIENT_AUTH
X509Certificate
RegisteredClient.getClientSettings.getX509CertificateSubjectDN()
如果需要验证 client 的另一个属性,例如主题备用名称 (SAN) 条目,以下示例显示如何使用证书验证程序的自定义实施进行配置:X509Certificate
X509ClientCertificateAuthenticationProvider
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
new OAuth2AuthorizationServerConfigurer();
http.apply(authorizationServerConfigurer);
authorizationServerConfigurer
.clientAuthentication(clientAuthentication ->
clientAuthentication
.authenticationProviders(configureX509ClientCertificateVerifier())
);
return http.build();
}
private Consumer<List<AuthenticationProvider>> configureX509ClientCertificateVerifier() {
return (authenticationProviders) ->
authenticationProviders.forEach((authenticationProvider) -> {
if (authenticationProvider instanceof X509ClientCertificateAuthenticationProvider) {
Consumer<OAuth2ClientAuthenticationContext> certificateVerifier = (clientAuthenticationContext) -> {
OAuth2ClientAuthenticationToken clientAuthentication = clientAuthenticationContext.getAuthentication();
RegisteredClient registeredClient = clientAuthenticationContext.getRegisteredClient();
X509Certificate[] clientCertificateChain = (X509Certificate[]) clientAuthentication.getCredentials();
X509Certificate clientCertificate = clientCertificateChain[0];
// TODO Verify Subject Alternative Name (SAN) entry
};
((X509ClientCertificateAuthenticationProvider) authenticationProvider)
.setCertificateVerifier(certificateVerifier);
}
});
}
自签名证书互助 TLS 方法
对于自签名证书互惠 TLS () 方法,证书验证程序的默认实现将使用该设置检索客户端的 JSON Web 密钥集,并期望找到与在 TLS 握手期间收到的客户端的匹配项。ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH
RegisteredClient.getClientSettings.getJwkSetUrl()
X509Certificate
该设置用于通过 JSON Web 密钥 (JWK) 集检索客户端的证书。
证书由证书集中单个 JWK 的参数表示。RegisteredClient.getClientSettings.getJwkSetUrl() x5c |
客户端 Certificate-Bound Access Token
在令牌端点使用 Mutual-TLS 客户端身份验证时,授权服务器能够将颁发的访问令牌绑定到客户端的 .
绑定是通过计算客户端的 SHA-256 指纹并将指纹与访问令牌相关联来完成的。
例如,JWT 访问令牌将在顶级(确认方法)声明中包含包含指纹的声明。X509Certificate
X509Certificate
x5t#S256
X509Certificate
cnf
将访问令牌绑定到客户端的令牌提供了在受保护资源访问期间实施所有权证明机制的能力。
例如,受保护的资源将获取客户端在 Mutual-TLS 身份验证期间使用的指纹,然后验证证书指纹是否与与访问令牌关联的声明匹配。X509Certificate
X509Certificate
x5t#S256
以下示例显示如何为客户端启用证书绑定访问令牌:
RegisteredClient mtlsClient = RegisteredClient.withId(UUID.randomUUID().toString())
.clientId("mtls-client")
.clientAuthenticationMethod(ClientAuthenticationMethod.TLS_CLIENT_AUTH)
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
.scope("scope-a")
.clientSettings(
ClientSettings.builder()
.x509CertificateSubjectDN("CN=mtls-client,OU=Spring Samples,O=Spring,C=US")
.build()
)
.tokenSettings(
TokenSettings.builder()
.x509CertificateBoundAccessTokens(true)
.build()
)
.build();