如何在同一个 Spring 引导应用程序中使用多个 'JWK Set Uri' 值?

How do I use multiple 'JWK Set Uri' values in the same Spring Boot app?

我需要使用两个不同的授权服务器(两个 Okta 实例)来验证来自单个 Spring 引导应用程序中的两个不同 Web 应用程序的身份验证令牌,这是一个 back-end REST API层.

目前我有一台资源服务器使用以下配置:

@Configuration
@EnableWebSecurity
public class ResourceServerSecurityConfig extends WebSecurityConfigurerAdapter {

  @Override
  protected void configure(HttpSecurity http) throws Exception{
    http
      .authorizeRequests().antMatchers("/public/**").permitAll()
      .anyRequest().authenticated()
      .and()
      .oauth2ResourceServer().jwt();
  }
}
spring.security.oauth2.resourceserver.jwt.issuer-uri=https://dev-X.okta.com/oauth2/default
spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://dev-X.okta.com/oauth2/default/v1/keys

并且在我的 Spring 引导应用程序(版本 2.2.4.RELEASE)中具有依赖项 spring-security-oauth2-resource-serverspring-security-oauth2-jose

我想要进入的最终状态是,根据请求中设置的自定义 HTTP header,我想选择我的 Spring 启动应用程序使用哪个 Okta 实例来解码和验证JWT 令牌。

理想情况下,我的配置文件中有两个属性如下:

jwkSetUri.X=https://dev-X.okta.com/oauth2/default/v1/keys
jwtIssuerUri.X=https://dev-X.okta.com/oauth2/default

jwkSetUri.Y=https://dev-Y.okta.com/oauth2/default/v1/keys
jwtIssuerUri.Y=https://dev-Y.okta.com/oauth2/default

我应该可以使用 RequestHeaderRequestMatcher 来匹配安全配置中的 header 值。我无法锻炼的是如何使用安全配置附带的两个不同的 oauth2ResourceServer 实例。

使用 spring 引导,现在无法开箱即用。 Spring Security 5.3 提供了执行此操作的功能(spring boot 2.2.6 仍然不支持 spring security 5.3)。 请参阅以下问题:

https://github.com/spring-projects/spring-security/issues/7857
https://github.com/spring-projects/spring-security/pull/7887

可以通过我提供的链接手动配置资源服务器以使用多个身份提供者。提供的链接主要用于 spring 启动 webflux 开发。对于基本 spring 引导 Web 开发,请观看此视频:

https://www.youtube.com/watch?v=ke13w8nab-k

从 Spring security 5.3+ 开始可以使用 JwtIssuerAuthenticationManagerResolver 对象

覆盖扩展 WebSecurityConfigurerAdapter

的配置 class 中的 configure(HttpSecurity http)
JwtIssuerAuthenticationManagerResolver authenticationManagerResolver = new JwtIssuerAuthenticationManagerResolver(
            "http://localhost:8080/auth/realms/SpringBootKeyClock",
            "https://accounts.google.com/o/oauth2/auth",
            "https://<subdomain>.okta.com/oauth2/default"
    );

http.cors()
            .and()
            .authorizeRequests()
            .antMatchers(HttpMethod.GET, "/user/info", "/api/foos/**")
            .hasAnyAuthority("SCOPE_email")
            .antMatchers(HttpMethod.POST, "/api/foos")
            .hasAuthority("SCOPE_profile")
            .anyRequest()
            .authenticated()
            .and()
            .oauth2ResourceServer(oauth2 -> oauth2.authenticationManagerResolver(authenticationManagerResolver));