|
此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Authorization Server 1.5.2! |
配置模型
默认配置
OAuth2AuthorizationServerConfiguration是一个@Configuration为 OAuth2 授权服务器提供最小的默认配置。
OAuth2AuthorizationServerConfiguration使用OAuth2AuthorizationServerConfigurer应用默认配置并注册一个SecurityFilterChain @Bean由支持 OAuth2 授权服务器的所有基础设施组件组成。
OAuth2 授权服务器SecurityFilterChain @Bean配置了以下默认协议端点:
仅当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 在默认配置中处于禁用状态。以下示例演示如何通过初始化OidcConfigurer:
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
OAuth2AuthorizationServerConfigurer.authorizationServer();
http
.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
.with(authorizationServerConfigurer, (authorizationServer) ->
authorizationServer
.oidc(Customizer.withDefaults()) // Initialize `OidcConfigurer`
);
return http.build();
}
除了默认协议端点外,OAuth2 授权服务器SecurityFilterChain @Bean配置了以下 OpenID Connect 1.0 协议端点:
| 默认情况下,OpenID Connect 1.0 客户端注册端点处于禁用状态,因为许多部署不需要动态客户端注册。 |
OAuth2AuthorizationServerConfiguration.jwtDecoder(JWKSource<SecurityContext>)是一种便利(static) 实用程序方法,可用于注册JwtDecoder @Bean,这是 OpenID Connect 1.0 UserInfo 端点和 OpenID Connect 1.0 客户端注册端点所必需的。 |
以下示例演示如何注册JwtDecoder @Bean:
@Bean
public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
}
的主要意图OAuth2AuthorizationServerConfiguration是提供一种方便的方法来为 OAuth2 授权服务器应用最小默认配置。但是,在大多数情况下,需要自定义配置。
自定义配置
OAuth2AuthorizationServerConfigurer提供了完全自定义 OAuth2 授权服务器安全配置的功能。
它允许您指定要使用的核心组件 - 例如RegisteredClientRepository,OAuth2AuthorizationService,OAuth2TokenGenerator,等。
此外,它还允许您自定义协议端点的请求处理逻辑,例如,授权端点、设备授权端点、设备验证端点、Tokens端点、Tokens自检端点等。
OAuth2AuthorizationServerConfigurer提供以下配置选项:
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
OAuth2AuthorizationServerConfigurer.authorizationServer();
http
.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
.with(authorizationServerConfigurer, (authorizationServer) ->
authorizationServer
.registeredClientRepository(registeredClientRepository) (1)
.authorizationService(authorizationService) (2)
.authorizationConsentService(authorizationConsentService) (3)
.authorizationServerSettings(authorizationServerSettings) (4)
.tokenGenerator(tokenGenerator) (5)
.clientAuthentication(clientAuthentication -> { }) (6)
.authorizationEndpoint(authorizationEndpoint -> { }) (7)
.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 (必填)用于管理新客户和现有客户。 |
| 2 | authorizationService():这OAuth2AuthorizationService用于管理新的和现有的授权。 |
| 3 | authorizationConsentService():这OAuth2AuthorizationConsentService用于管理新的和现有的授权同意。 |
| 4 | authorizationServerSettings():这AuthorizationServerSettings (必填)用于自定义 OAuth2 授权服务器的配置设置。 |
| 5 | tokenGenerator():这OAuth2TokenGenerator用于生成 OAuth2 授权服务器支持的Tokens。 |
| 6 | clientAuthentication():OAuth2 客户端身份验证的配置器。 |
| 7 | authorizationEndpoint():OAuth2 授权端点的配置器。 |
| 8 | deviceAuthorizationEndpoint():OAuth2 设备授权端点的配置器。 |
| 9 | deviceVerificationEndpoint():OAuth2 设备验证端点的配置程序。 |
| 10 | tokenEndpoint():OAuth2 Tokens端点的配置器。 |
| 11 | tokenIntrospectionEndpoint():OAuth2 Tokens自检端点的配置器。 |
| 12 | tokenRevocationEndpoint():OAuth2 Tokens吊销端点的配置器。 |
| 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 客户端注册端点的配置器。 |
配置授权服务器设置
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是必需组件。 |
@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();
}
这AuthorizationServerContext是保存授权服务器运行时环境信息的上下文对象。
它提供对AuthorizationServerSettings以及“当前”发行人标识符。
如果颁发者标识符未在AuthorizationServerSettings.builder().issuer(String),则从当前请求中解析。 |
这AuthorizationServerContext可通过AuthorizationServerContextHolder,它通过使用ThreadLocal. |
配置客户端身份验证
OAuth2ClientAuthenticationConfigurer提供自定义 OAuth2 客户端身份验证的功能。
它定义了扩展点,允许您自定义客户端身份验证请求的预处理、主处理和后处理逻辑。
OAuth2ClientAuthenticationConfigurer提供以下配置选项:
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
OAuth2AuthorizationServerConfigurer.authorizationServer();
http
.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
.with(authorizationServerConfigurer, (authorizationServer) ->
authorizationServer
.clientAuthentication(clientAuthentication ->
clientAuthentication
.authenticationConverter(authenticationConverter) (1)
.authenticationConverters(authenticationConvertersConsumer) (2)
.authenticationProvider(authenticationProvider) (3)
.authenticationProviders(authenticationProvidersConsumer) (4)
.authenticationSuccessHandler(authenticationSuccessHandler) (5)
.errorResponseHandler(errorResponseHandler) (6)
)
);
return http.build();
}
| 1 | authenticationConverter():添加一个AuthenticationConverter (预处理器)尝试从中提取客户端凭据时使用HttpServletRequest设置为OAuth2ClientAuthenticationToken. |
| 2 | authenticationConverters():将Consumer提供对List默认和(可选)添加AuthenticationConverter允许添加、删除或自定义特定的AuthenticationConverter. |
| 3 | authenticationProvider():添加一个AuthenticationProvider (主处理器)用于验证OAuth2ClientAuthenticationToken. |
| 4 | authenticationProviders():将Consumer提供对List默认和(可选)添加AuthenticationProvider允许添加、删除或自定义特定的AuthenticationProvider. |
| 5 | authenticationSuccessHandler():这AuthenticationSuccessHandler (后处理器)用于处理成功的客户端身份验证并关联OAuth2ClientAuthenticationToken到SecurityContext. |
| 6 | errorResponseHandler():这AuthenticationFailureHandler (后处理器)用于处理失败的客户端身份验证并返回OAuth2Error响应. |
OAuth2ClientAuthenticationConfigurer配置OAuth2ClientAuthenticationFilter并将其注册到 OAuth2 授权服务器SecurityFilterChain @Bean.OAuth2ClientAuthenticationFilter是Filter处理客户端身份验证请求。
默认情况下,OAuth2 Tokens端点、OAuth2 Tokens检测端点和 OAuth2 Tokens吊销端点需要客户端身份验证。
支持的客户端身份验证方法包括client_secret_basic,client_secret_post,private_key_jwt,client_secret_jwt,tls_client_auth,self_signed_tls_client_auth和none(公共客户端)。
OAuth2ClientAuthenticationFilter配置为以下默认值:
-
AuthenticationConverter— 一个DelegatingAuthenticationConverter由JwtClientAssertionAuthenticationConverter,X509ClientCertificateAuthenticationConverter,ClientSecretBasicAuthenticationConverter,ClientSecretPostAuthenticationConverter和PublicClientAuthenticationConverter. -
AuthenticationManager— 一个AuthenticationManager由JwtClientAssertionAuthenticationProvider,X509ClientCertificateAuthenticationProvider,ClientSecretAuthenticationProvider和PublicClientAuthenticationProvider. -
AuthenticationSuccessHandler— 将“已验证”关联的内部实现OAuth2ClientAuthenticationToken(当前Authentication) 设置为SecurityContext. -
AuthenticationFailureHandler— 使用OAuth2Error与OAuth2AuthenticationException返回 OAuth2 错误响应。
自定义 Jwt 客户端断言验证
JwtClientAssertionDecoderFactory.DEFAULT_JWT_VALIDATOR_FACTORY是默认工厂,它提供了OAuth2TokenValidator<Jwt>对于指定的RegisteredClient并用于验证iss,sub,aud,exp和nbf的声明Jwt客户端断言。
JwtClientAssertionDecoderFactory提供覆盖默认值Jwt通过提供类型Function<RegisteredClient, OAuth2TokenValidator<Jwt>>自setJwtValidatorFactory().
JwtClientAssertionDecoderFactory是默认值JwtDecoderFactory使用者JwtClientAssertionAuthenticationProvider这提供了一个JwtDecoder对于指定的RegisteredClient并用于验证JwtOAuth2 客户端身份验证期间的持有者Tokens。 |
自定义的常见用例JwtClientAssertionDecoderFactory是为了验证Jwt客户端断言。
以下示例演示如何配置JwtClientAssertionAuthenticationProvider与定制的JwtClientAssertionDecoderFactory验证Jwt客户端断言:
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
OAuth2AuthorizationServerConfigurer.authorizationServer();
http
.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
.with(authorizationServerConfigurer, (authorizationServer) ->
authorizationServer
.clientAuthentication(clientAuthentication ->
clientAuthentication
.authenticationProviders(configureJwtClientAssertionValidator())
)
);
return http.build();
}
private Consumer<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用于对客户端进行身份验证X509Certificate链收到时ClientAuthenticationMethod.TLS_CLIENT_AUTH或ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH方法在 OAuth2 客户端身份验证期间使用。它还由一个“证书验证器”组成,用于验证客户端的内容X509CertificateTLS 握手成功完成后。
PKI 互 TLS 方法
对于 PKI 互 TLS (ClientAuthenticationMethod.TLS_CLIENT_AUTH) 方法,证书验证程序的默认实现验证客户端的主题可分辨名X509Certificate反对设定RegisteredClient.getClientSettings.getX509CertificateSubjectDN().
如果需要验证客户端的其他属性X509Certificate,例如,使用者备用名称 (SAN) 条目,以下示例显示如何配置X509ClientCertificateAuthenticationProvider使用证书验证程序的自定义实现:
@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
OAuth2AuthorizationServerConfigurer.authorizationServer();
http
.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
.with(authorizationServerConfigurer, (authorizationServer) ->
authorizationServer
.clientAuthentication(clientAuthentication ->
clientAuthentication
.authenticationProviders(configureX509ClientCertificateVerifier())
)
);
return http.build();
}
private Consumer<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 (ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH) 方法,证书验证器的默认实现将使用设置RegisteredClient.getClientSettings.getJwkSetUrl()并期望找到与客户匹配的X509Certificate在 TLS 握手期间收到。
这RegisteredClient.getClientSettings.getJwkSetUrl()设置用于通过 JSON Web 密钥 (JWK) 集检索客户端的证书。证书用x5c集合中单个 JWK 的参数。 |
客户端证书绑定访问Tokens
在Tokens端点使用互 TLS 客户端身份验证时,授权服务器能够将颁发的访问Tokens绑定到客户端的X509Certificate. 绑定是通过计算客户端的X509Certificate并将指纹与访问Tokens相关联。例如,JWT 访问Tokens将包括x5t#S256声明,其中包含X509Certificate指纹,在顶级cnf(确认方法)索赔。
将访问Tokens绑定到客户端的X509Certificate提供在受保护资源访问期间实现所有权证明机制的能力。例如,受保护的资源将获取客户端的X509Certificate在相互 TLS 身份验证期间使用,然后验证证书指纹是否与x5t#S256与访问Tokens关联的声明。
以下示例演示如何为客户端启用证书绑定访问Tokens:
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();