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

配置模型

默认配置

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

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

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 {
	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 协议终端节点: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 =
			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 授权服务器支持的令牌。
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");
	}

	...

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

OAuth2ClientAuthenticationConfigurer配置OAuth2ClientAuthenticationFilter并将其注册到 OAuth2 授权服务器SecurityFilterChain @Bean.OAuth2ClientAuthenticationFilterFilter处理客户端身份验证请求。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_authnone(公共客户端)。spring-doc.cadn.net.cn

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

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

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

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

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

自定义 Jwt 客户端断言验证

JwtClientAssertionDecoderFactory.DEFAULT_JWT_VALIDATOR_FACTORY是默认工厂,它提供OAuth2TokenValidator<Jwt>对于指定的RegisteredClient,用于验证iss,sub,aud,expnbf的声明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 =
			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用于验证客户端X509Certificatechain 接收时间ClientAuthenticationMethod.TLS_CLIENT_AUTHClientAuthenticationMethod.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 =
			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 方法

对于自签名证书 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();