Spring Authorization Server 配置模型

时间:2024-02-26 06:58:42

配置模型

默认配置

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

OAuth2AuthorizationServerConfiguration 使用 OAuth2AuthorizationServerConfigurer 应用默认配置,并注册一个由支持 OAuth2 授权服务器的所有基础设施组件组成的 SecurityFilterChain @Bean。只有当注册了 JWKSource @Bean 时,才会配置 JWK Set 端点。

以下示例显示如何使用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提供程序配置终结点
  • OpenID Connect 1.0注销端点
  • OpenID Connect 1.0 UserInfo端点

注意:
默认情况下,OpenID Connect 1.0客户端注册端点处于禁用状态,因为许多部署不需要动态客户端注册

提示:
OAuth2AuthorizationServerConfiguration.jwtDecoder(JWKSource<SecurityContext>)是一种方便的(静态)实用程序方法,可用于注册jwtDecoder@Bean,这是OpenID Connect 1.0 UserInfo端点和OpenID Connect 1.0Client Registration端点所必需的。

以下示例显示如何注册JwtDecoder@Bean:

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

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

定制配置

OAuth2AuthorizationServerConfigurer提供了完全自定义OAuth2授权服务器的安全配置的功能。它允许您指定要使用的核心组件,例如RegisteredClientPositionory、OAuth2AuthorizationService、OAuth2TokenGenerator等。此外,它还允许您自定义协议端点的请求处理逻辑,例如,授权端点、设备授权端点、装置验证端点、令牌端点、令牌内省端点等。
OAuth2AuthorizationServerConfigurer提供以下配置选项:

@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
	OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
		new OAuth2AuthorizationServerConfigurer();
	http.apply(authorizationServerConfigurer);

	authorizationServerConfigurer
		.registeredClientRepository(registeredClientRepository) //用于管理新客户端和现有客户端的(必须)
		.authorizationService(authorizationService)//用于管理新授权和现有授权
		.authorizationConsentService(authorizationConsentService)//管理新的和现有的授权许可。
		.authorizationServerSettings(authorizationServerSettings)//自定义OAuth2授权服务器的配置设置(必填)
		.tokenGenerator(tokenGenerator)//生成OAuth2授权服务器支持的令牌
		.clientAuthentication(clientAuthentication -> { })//OAuth2客户端身份验证的配置程序。
		.authorizationEndpoint(authorizationEndpoint -> { })//OAuth2授权端点的配置程序
		.deviceAuthorizationEndpoint(deviceAuthorizationEndpoint -> { })//OAuth2设备授权端点的配置程序
		.deviceVerificationEndpoint(deviceVerificationEndpoint -> { })//OAuth2设备验证端点的配置程序。
		.tokenEndpoint(tokenEndpoint -> { })//OAuth2令牌端点的配置程序
		.tokenIntrospectionEndpoint(tokenIntrospectionEndpoint -> { })//OAuth2令牌内省端点的配置程序
		.tokenRevocationEndpoint(tokenRevocationEndpoint -> { })//OAuth2令牌撤销端点的配置程序。
		.authorizationServerMetadataEndpoint(authorizationServerMetadataEndpoint -> { })//OAuth2授权服务器元数据终结点的配置程序
		.oidc(oidc -> oidc
			.providerConfigurationEndpoint(providerConfigurationEndpoint -> { })//OpenID Connect 1.0提供程序配置端点的配置程序
			.logoutEndpoint(logoutEndpoint -> { })//OpenID Connect 1.0注销端点的配置程序
			.userInfoEndpoint(userInfoEndpoint -> { })//OpenID Connect 1.0用户信息端点的配置程序
			.clientRegistrationEndpoint(clientRegistrationEndpoint -> { })//OpenID Connect 1.0客户端注册端点的配置程序
		);

	return http.build();
}

配置授权服务器配置

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)将自动注册 如果尚未提供@Bean AuthorizationServerSettings 。
    以下示例显示如何自定义配置设置并注册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是一个上下文对象,用于保存AuthorizationServer运行时环境的信息。它提供对AuthorizationServerSettings和“当前”颁发者标识符的访问

配置客户端授权

OAuth2ClientAuthenticationConfigurer提供了自定义OAuth2客户端身份验证的功能。它定义了扩展点,使您可以自定义客户端身份验证请求的预处理、主处理和后处理逻辑。
OAuth2ClientAuthenticationConfigurer提供以下配置选项:

@Bean
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
	OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
		new OAuth2AuthorizationServerConfigurer();
	http.apply(authorizationServerConfigurer);

	authorizationServerConfigurer
		.clientAuthentication(clientAuthentication ->
			clientAuthentication
				.authenticationConverter(authenticationConverter) //将尝试从HttpServlet请求提取客户端凭据时使用的AuthenticationConverter(预处理器)添加到OAuth2ClientAuthenticationToken的实例中。
				.authenticationConverters(authenticationConvertersConsumer) //设置提供对默认和(可选)添加的AuthenticationConverter列表的访问权限的使用者,允许添加、删除或自定义特定的AuthenticationConverter。
				.authenticationProvider(authenticationProvider) //添加用于对OAuth2ClientAuthenticationToken进行身份验证的AuthenticationProvider(主处理器)。
				.authenticationProviders(authenticationProvidersConsumer)//设置提供对默认和(可选)添加的AuthenticationProvider列表的访问权限的使用者,允许添加、删除或自定义特定AuthenticationProvider。
				.authenticationSuccessHandler(authenticationSuccessHandler)//AuthenticationSuccessHandler(后处理器),用于处理成功的客户端身份验证并将OAuth2ClientAuthenticationToken与SecurityContext关联。
				.errorResponseHandler(errorResponseHandler)//AuthenticationFailureHandler(后处理器),用于处理失败的客户端身份验证并返回OAuth2Error响应。
		);

	return http.build();
}

OAuth2ClientAuthenticationConfigurer配置OAuth2CClientAuthenticationFilter,并将其注册到OAuth2授权服务器SecurityFilterChain@Bean。OAuth2ClientAuthenticationFilter是处理客户端身份验证请求的筛选器。

默认情况下,OAuth2 Token端点、OAuth2 Token Introspection端点和OAuth2 Token Revocation端点需要客户端身份验证。支持的客户端身份验证方法有client_secret_basic、client_secret_post、private_key_jwt、client_secret_jwt和none(公共客户端)。

OAuth2ClientAuthenticationFilter配置为具有以下默认值:

  • AuthenticationConverter — A DelegatingAuthenticationConverter composed of JwtClientAssertionAuthenticationConverter, ClientSecretBasicAuthenticationConverter, ClientSecretPostAuthenticationConverter, and PublicClientAuthenticationConverter.

  • AuthenticationManager — An AuthenticationManager composed of JwtClientAssertionAuthenticationProvider, ClientSecretAuthenticationProvider, and PublicClientAuthenticationProvider.

  • AuthenticationSuccessHandler — An internal implementation that associates the “authenticated” OAuth2ClientAuthenticationToken (current Authentication) to the SecurityContext.

  • AuthenticationFailureHandler — An internal implementation that uses the OAuth2Error associated with the OAuth2AuthenticationException to return the OAuth2 error response.

自定义Jwt客户端验证

JwtClientAssertionDecoderFactory。DEFAULT_JWT_VALIDATOR_FACTORY是为指定的RegisteredClient提供OAuth2TokenValidator<JWT>的默认工厂,用于验证JWT客户端断言的iss、sub、aud、exp和nbf声明。
JwtClientAssertionDecoderFactory通过提供类型为Function<RegisteredClient,OAuth2TokenValidator<Jwt>>的自定义工厂来设置JwtValidatorFactory(),从而提供覆盖默认Jwt客户端断言验证的功能。
JwtClientAssertionDecoderFactory是JwtClientAssetAuthenticationProvider使用的默认JwtDecoderFactory,它为指定的RegisteredClient提供JwtDecode,并用于在OAuth2客户端身份验证期间验证JwtBearer令牌。
自定义JwtClientAssertionDecoderFactory的一个常见用例是验证JwtClient断言中的其他声明。
以下示例显示如何使用自定义的JwtClientAssertionDecoderFactory配置JwtClientAssetAuthenticationProvider,该JwtClient AssertiondecoderFactory验证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);
			}
		});
}