我有一些带有 Spring Security 的 Spring 项目,并且仅使用 AWS Cognito 进行身份验证。 其中一个项目(我们称之为
authorities-api
)负责管理用户权限。所以我有一个自定义的用户内省端点。
此流程由
authentication code
覆盖并且运行良好。这是现在有效的 SecurityFilterChain
:
@Bean
fun filterChain(httpSecurity: HttpSecurity): SecurityFilterChain {
httpSecurity
.crsf { //omitted code }
.sessionManagement { //omitted code }
.authorizeHttpRequests { //omitted code }
.httpBasic().disable()
.oauth2ResourceServer { resourceServer ->
//This works and calls the authorities-api to get user authorities
resourceServer.opaqueToken { it.introspector(jwtOpaqueTokenIntrospector) }
}
.cors { //omitted code }
}
但现在我还想确保 API 之间的通信安全。 我已经使用
client credentials
流程在 Cognito 的用户池中创建了一个应用程序客户端。我已经通过创建以下 bean 设置了 API:
@Bean
fun clientRegistration(
@Value("\${path.to.clientId}") clientId: String,
@Value("\${path.to.clientSecret}") clientSecret: String,
@Value("\${path.to.tokenUri}") tokenUri: String,
@Value("\${path.to.registrationId}") registrationId: String): ClientRegistration {
return ClientRegistration
.withRegistrationId(registrationId)
.tokenUri(tokenUri)
.clientId(clientId)
.clientSecret(clientSecret)
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
.build()
}
@Bean
fun clientRegistrationRepository() = InMemoryClientRegistrationRepository(clientRegistration())
我还有
webClient
配置:
@Bean
fun webClient(
clientRegistrationRepository: ClientRegistrationRepository,
@Value("\${path.to.registrationId}") registrationId: String
): WebClient {
val clientService = InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository)
val authorizedClientManager =
AuthorizedClientServiceOAuth2AuthorizedClientManager(clientRegistrationRepository, clientService)
val oauth = ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager)
oauth.setDefaultClientRegistrationId(registrationId)
return WebClient.builder().filter(oauth).build()
}
然后,我添加了以下行来配置客户端:
@Bean
fun filterChain(httpSecurity: HttpSecurity): SecurityFilterChain {
httpSecurity
.crsf { //omitted code }
.sessionManagement { //omitted code }
.authorizeHttpRequests { //omitted code }
.httpBasic().disable()
.oauth2Client { it.clientRegistrationRepository(clientRegistrationRepository()) } //this line
.oauth2ResourceServer { resourceServer ->
//This works and calls the authorities-api to get user authorities
resourceServer.opaqueToken { it.introspector(jwtOpaqueTokenIntrospector) }
}
.cors { //omitted code }
}
有了这个 bean,我认为让 Spring 理解这两个流程会更容易,但由于 Cognito 仅将生成的访问令牌从
authentication code
到 client credentials
区别为几个字段(scope
表示客户端凭据,redirect uri
表示例如,身份验证代码),Spring 仍在向用户内省端点发出请求,这是没有必要的。
如何在同一个 API 中拥有两个 OAuth2 流,并仅在流为
authorization code
时才调用用户自省?
流(所有流)被客户端用来从授权服务器获取令牌。
客户端使用此令牌来授权对资源服务器的请求。
资源服务器验证访问令牌并获取与其关联的声明,方法是在它是 JWT 时对其进行解码(使用从颁发它的授权服务器获取的公钥)或在授权服务器上进行内省(无论什么格式)。
客户端用于从授权服务器获取令牌的流程与资源服务器无关,并且不会改变该资源服务器验证令牌或获取与其关联的声明的方式。