配置模型

默认配置

OAuth2AuthorizationServerConfiguration是一个@Configuration,为OAuth2授权服务器提供最小的默认配置。

OAuth2AuthorizationServerConfiguration使用OAuth2AuthorizationServerConfigurer来应用默认配置,并注册一个由支持OAuth2授权服务器的所有基础组件组成的SecurityFilterChain @Bean

OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(HttpSecurity)是一个方便的(static)实用方法,将默认的OAuth2安全配置应用于HttpSecurity
SecurityFilterChain @Bean配置了以下默认的协议端点:

只有在注册了JWKSource<SecurityContext> @Bean时,才会配置JWK集合端点。

以下示例显示了如何使用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来启用OpenID Connect 1.0:

@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协议端点:

默认情况下禁用了OpenID Connect 1.0客户端注册端点,因为许多部署不需要动态客户端注册。
OAuth2AuthorizationServerConfiguration.jwtDecoder(JWKSource<SecurityContext>)是一个方便的(static)实用方法,可用于注册JwtDecoder @Bean,这是OpenID Connect 1.0用户信息端点OpenID Connect 1.0客户端注册端点所必需的。

以下示例显示了如何注册一个JwtDecoder @Bean

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

OAuth2AuthorizationServerConfiguration的主要目的是提供一种便捷的方法,应用OAuth2授权服务器的最小默认配置。然而,在大多数情况下,将需要自定义配置。

自定义配置

OAuth2AuthorizationServerConfigurer提供了完全定制OAuth2授权服务器安全配置的能力。它允许您指定要使用的核心组件 - 例如,RegisteredClientRepositoryOAuth2AuthorizationServiceOAuth2TokenGenerator等。此外,它还允许您定制协议端点的请求处理逻辑 - 例如,授权端点设备授权端点设备验证端点令牌端点令牌内省端点等。

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必需)。
2 authorizationService(): 用于管理新建和现有授权的OAuth2AuthorizationService
3 authorizationConsentService(): 用于管理新建和现有授权同意的OAuth2AuthorizationConsentService
4 authorizationServerSettings(): 用于自定义配置OAuth2授权服务器的AuthorizationServerSettings必需)。
5 tokenGenerator(): 用于生成OAuth2授权服务器支持的令牌的OAuth2TokenGenerator
6 clientAuthentication(): 用于配置OAuth2客户端认证的配置器。
7 authorizationEndpoint(): 用于OAuth2授权端点的配置器。
8 deviceAuthorizationEndpoint(): 用于OAuth2设备授权端点的配置器。
9 deviceVerificationEndpoint(): 用于OAuth2设备验证端点的配置器。
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用户信息端点的配置器。
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 =
		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():设置提供访问默认和(可选)添加的AuthenticationConverter列表的Consumer,允许添加、删除或自定义特定的AuthenticationConverter
3 authenticationProvider():添加一个AuthenticationProvider主处理器),用于对OAuth2ClientAuthenticationToken进行身份验证。
4 authenticationProviders():设置提供访问默认和(可选)添加的AuthenticationProvider列表的Consumer,允许添加、删除或自定义特定的AuthenticationProvider
5 authenticationSuccessHandler():用于处理成功的客户端认证并将OAuth2ClientAuthenticationToken关联到SecurityContextAuthenticationSuccessHandler后处理器)。
6 errorResponseHandler():用于处理失败的客户端认证并返回OAuth2Error响应AuthenticationFailureHandler后处理器)。

OAuth2ClientAuthenticationConfigurer配置了OAuth2ClientAuthenticationFilter并将其注册到OAuth2授权服务器SecurityFilterChain@Bean中。OAuth2ClientAuthenticationFilter是处理客户端认证请求的Filter

默认情况下,OAuth2令牌端点OAuth2令牌内省端点OAuth2令牌撤销端点需要客户端认证。支持的客户端认证方法包括client_secret_basicclient_secret_postprivate_key_jwtclient_secret_jwtnone(公共客户端)。

OAuth2ClientAuthenticationFilter配置了以下默认值:

  • AuthenticationConverter — 由JwtClientAssertionAuthenticationConverterClientSecretBasicAuthenticationConverterClientSecretPostAuthenticationConverterPublicClientAuthenticationConverter组成的DelegatingAuthenticationConverter

  • AuthenticationManager — 由JwtClientAssertionAuthenticationProviderClientSecretAuthenticationProviderPublicClientAuthenticationProvider组成的AuthenticationManager

  • AuthenticationSuccessHandler — 一个内部实现,将“经过身份验证”的OAuth2ClientAuthenticationToken(当前Authentication)关联到SecurityContext

  • AuthenticationFailureHandler — 一个内部实现,使用与OAuth2AuthenticationException关联的OAuth2Error来返回OAuth2错误响应。

自定义Jwt客户端断言验证

JwtClientAssertionDecoderFactory.DEFAULT_JWT_VALIDATOR_FACTORY是默认工厂,为指定的RegisteredClient提供一个OAuth2TokenValidator<Jwt>,用于验证Jwt客户端断言的isssubaudexpnbf声明。

JwtClientAssertionDecoderFactory提供了通过提供类型为Function<RegisteredClient, OAuth2TokenValidator<Jwt>>的自定义工厂来覆盖默认的Jwt客户端断言验证的能力,方法是调用setJwtValidatorFactory()

JwtClientAssertionDecoderFactoryJwtClientAssertionAuthenticationProvider使用的默认JwtDecoderFactory,为指定的RegisteredClient提供一个JwtDecoder,用于在OAuth2客户端认证期间对Jwt Bearer Token进行身份验证。
JwtClientAssertionDecoderFactory的常见用例是验证 Jwt客户端断言中的附加声明。

以下示例显示了如何使用自定义JwtClientAssertionDecoderFactory配置JwtClientAssertionAuthenticationProvider,该配置验证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);
			}
		});
}