此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Authorization Server 1.4.0!spring-doc.cadn.net.cn

配置模型

默认配置

OAuth2AuthorizationServerConfiguration是一个@Configuration,它为 OAuth2 授权服务器提供最低的默认配置。spring-doc.cadn.net.cn

OAuth2AuthorizationServerConfiguration使用OAuth2AuthorizationServerConfigurer要应用默认配置并注册SecurityFilterChain @Bean由支持 OAuth2 授权服务器的所有基础结构组件组成。spring-doc.cadn.net.cn

OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(HttpSecurity)是一种便利 (static) 实用程序方法,该方法将默认 OAuth2 安全配置应用于HttpSecurity.

OAuth2 授权服务器SecurityFilterChain @Bean配置了以下默认协议终端节点:spring-doc.cadn.net.cn

仅当 JWK Set 的JWKSource<SecurityContext> @Bean已注册。

以下示例演示如何使用OAuth2AuthorizationServerConfiguration要应用最低默认配置,请执行以下作:spring-doc.cadn.net.cn

@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:spring-doc.cadn.net.cn

@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
	OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);

	http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
		.oidc(Customizer.withDefaults());	// Initialize `OidcConfigurer`

	return http.build();
}

除了默认协议端点之外,OAuth2 授权服务器SecurityFilterChain @Bean配置了以下 OpenID Connect 1.0 协议终端节点:spring-doc.cadn.net.cn

默认情况下,OpenID Connect 1.0 客户端注册终端节点处于禁用状态,因为许多部署不需要动态客户端注册。
OAuth2AuthorizationServerConfiguration.jwtDecoder(JWKSource<SecurityContext>)是一种便利 (static) 实用程序方法,可用于注册JwtDecoder @Bean,这是 OpenID Connect 1.0 UserInfo 终端节点和 OpenID Connect 1.0 客户端注册终端节点所必需的。

以下示例演示如何注册JwtDecoder @Bean:spring-doc.cadn.net.cn

@Bean
public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
	return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
}

的主要意图OAuth2AuthorizationServerConfiguration是为了提供一种方便的方法来为 OAuth2 授权服务器应用最低默认配置。但是,在大多数情况下,需要自定义配置。spring-doc.cadn.net.cn

自定义配置

OAuth2AuthorizationServerConfigurer提供完全自定义 OAuth2 授权服务器安全配置的能力。 它允许您指定要使用的核心组件 - 例如,RegisteredClientRepository,OAuth2AuthorizationService,OAuth2TokenGenerator等。 此外,它还允许您自定义协议终端节点的请求处理逻辑,例如,授权终端节点、设备授权终端节点、设备验证终端节点、令牌终端节点、令牌自检终端节点等。spring-doc.cadn.net.cn

OAuth2AuthorizationServerConfigurer提供以下配置选项:spring-doc.cadn.net.cn

@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 (必需)用于管理新客户和现有客户。
2 authorizationService():这OAuth2AuthorizationService用于管理新的和现有的授权。
3 authorizationConsentService():这OAuth2AuthorizationConsentService用于管理新的和现有的授权同意。
4 authorizationServerSettings():这AuthorizationServerSettings (必需)用于自定义 OAuth2 授权服务器的配置设置。
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对于协议终端节点,如下所示:spring-doc.cadn.net.cn

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:spring-doc.cadn.net.cn

@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是保存 Authorization Server 运行时环境信息的上下文对象。 它提供对AuthorizationServerSettings以及 “current” issuer 标识符。spring-doc.cadn.net.cn

如果未在AuthorizationServerSettings.builder().issuer(String),则从当前请求中解析。
这AuthorizationServerContext可通过AuthorizationServerContextHolder,它通过使用ThreadLocal.

配置客户端身份验证

OAuth2ClientAuthenticationConfigurer提供自定义 OAuth2 客户端身份验证的功能。 它定义了扩展点,允许您自定义客户端身份验证请求的预处理、主处理和后处理逻辑。spring-doc.cadn.net.cn

OAuth2ClientAuthenticationConfigurer提供以下配置选项:spring-doc.cadn.net.cn

@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():设置Consumer提供对Listof default 和 (可选) addedAuthenticationConverter允许添加、删除或自定义特定AuthenticationConverter.
3 authenticationProvider():添加AuthenticationProvider (主处理器)用于验证OAuth2ClientAuthenticationToken.
4 authenticationProviders():设置Consumer提供对Listof default 和 (可选) addedAuthenticationProvider允许添加、删除或自定义特定AuthenticationProvider.
5 authenticationSuccessHandler():这AuthenticationSuccessHandler (后处理器)用于处理成功的客户端身份验证并将OAuth2ClientAuthenticationToken到SecurityContext.
6 errorResponseHandler():这AuthenticationFailureHandler (后处理器)用于处理失败的客户端身份验证并返回OAuth2Error响应.

OAuth2ClientAuthenticationConfigurer配置OAuth2ClientAuthenticationFilter并将其注册到 OAuth2 授权服务器SecurityFilterChain @Bean.OAuth2ClientAuthenticationFilter是Filter处理客户端身份验证请求。spring-doc.cadn.net.cn

默认情况下,OAuth2 令牌端点、OAuth2 令牌自检端点和 OAuth2 令牌吊销端点需要客户端身份验证。 支持的客户端身份验证方法包括client_secret_basic,client_secret_post,private_key_jwt,client_secret_jwt,tls_client_auth,self_signed_tls_client_auth和none(公共客户端)。spring-doc.cadn.net.cn

OAuth2ClientAuthenticationFilter配置了以下默认值:spring-doc.cadn.net.cn

  • AuthenticationConverter— 一个DelegatingAuthenticationConverter组成JwtClientAssertionAuthenticationConverter,X509ClientCertificateAuthenticationConverter,ClientSecretBasicAuthenticationConverter,ClientSecretPostAuthenticationConverter和PublicClientAuthenticationConverter.spring-doc.cadn.net.cn

  • AuthenticationManager— 一个AuthenticationManager组成JwtClientAssertionAuthenticationProvider,X509ClientCertificateAuthenticationProvider,ClientSecretAuthenticationProvider和PublicClientAuthenticationProvider.spring-doc.cadn.net.cn

  • AuthenticationSuccessHandler— 将 “authenticated” 关联的内部实现OAuth2ClientAuthenticationToken(当前Authentication) 到SecurityContext.spring-doc.cadn.net.cn

  • AuthenticationFailureHandler— 使用OAuth2Error与OAuth2AuthenticationException返回 OAuth2 错误响应。spring-doc.cadn.net.cn

自定义 Jwt 客户端断言验证

JwtClientAssertionDecoderFactory.DEFAULT_JWT_VALIDATOR_FACTORY是默认工厂,它提供OAuth2TokenValidator<Jwt>对于指定的RegisteredClient,用于验证iss,sub,aud,exp和nbf的声明Jwtclient 断言。spring-doc.cadn.net.cn

JwtClientAssertionDecoderFactory提供覆盖默认Jwt客户端断言验证,方法是提供Function<RegisteredClient, OAuth2TokenValidator<Jwt>>自setJwtValidatorFactory().spring-doc.cadn.net.cn

JwtClientAssertionDecoderFactory是默认值JwtDecoderFactory使用者JwtClientAssertionAuthenticationProvider,它提供了一个JwtDecoder对于指定的RegisteredClient,用于验证JwtOAuth2 客户端身份验证期间的 Bearer Token。

自定义的常见用例JwtClientAssertionDecoderFactory验证Jwtclient 断言。spring-doc.cadn.net.cn

以下示例显示如何配置JwtClientAssertionAuthenticationProvider使用自定义的JwtClientAssertionDecoderFactory验证Jwt客户端断言:spring-doc.cadn.net.cn

@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用于验证客户端X509Certificatechain 接收时间ClientAuthenticationMethod.TLS_CLIENT_AUTH或ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH方法在 OAuth2 客户端身份验证期间使用。 它还由一个 “Certificate Verifier” 组成,用于验证客户端的内容X509Certificate在 TLS 握手成功完成后。spring-doc.cadn.net.cn

PKI 互助 TLS 方法

对于 PKI 互助 TLS (ClientAuthenticationMethod.TLS_CLIENT_AUTH) 方法中,证书验证程序的默认实现会验证客户端的使用者专有名称X509Certificate与环境相反RegisteredClient.getClientSettings.getX509CertificateSubjectDN().spring-doc.cadn.net.cn

如果需要验证客户端的其他属性X509Certificate,例如,主题备用名称 (SAN) 条目,以下示例显示如何配置X509ClientCertificateAuthenticationProvider使用证书验证程序的自定义实现:spring-doc.cadn.net.cn

@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 方法

对于自签名证书 mutual-TLS (ClientAuthenticationMethod.SELF_SIGNED_TLS_CLIENT_AUTH) 方法,则证书验证程序的默认实现将使用设置RegisteredClient.getClientSettings.getJwkSetUrl()并期望找到与客户的匹配项X509Certificate在 TLS 握手期间接收。spring-doc.cadn.net.cn

这RegisteredClient.getClientSettings.getJwkSetUrl()设置用于通过 JSON Web 密钥 (JWK) 集检索客户端的证书。 证书用x5c参数。

客户端 Certificate-Bound Access Token

当在令牌端点使用 Mutual-TLS 客户端身份验证时,授权服务器能够将颁发的访问令牌绑定到客户端的X509Certificate. 绑定是通过计算客户端的 SHA-256 指纹来完成的X509Certificate以及将指纹与访问令牌相关联。 例如,JWT 访问令牌将包含一个x5t#S256claim 中包含X509Certificate指纹,在顶级cnf(确认方法) 声明。spring-doc.cadn.net.cn

将访问令牌绑定到客户端的X509Certificate提供在受保护资源访问期间实施所有权证明机制的能力。 例如,受保护的资源将获取客户端的X509Certificate在 Mutual-TLS 身份验证期间使用,然后验证证书指纹是否与x5t#S256与访问令牌关联的 claim 中。spring-doc.cadn.net.cn

以下示例显示如何为客户端启用证书绑定访问令牌:spring-doc.cadn.net.cn

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();