spring-security-oauth2 JwkTokenStore 与自定义用户详细信息服务

Posted

技术标签:

【中文标题】spring-security-oauth2 JwkTokenStore 与自定义用户详细信息服务【英文标题】:spring-security-oauth2 JwkTokenStore with custom user details service 【发布时间】:2017-12-11 01:06:04 【问题描述】:

我有一个富网络(基于反应的)前端应用程序,它向后端 ResourceServer 应用程序发送请求。请求在标头中使用 JWT 发送以进行身份​​验证。我的设置针对 Okta 授权服务器进行身份验证,并从单独的服务中检索组/权限。

我将后端服务器设置为带有 Spring Security Oauth2 资源服务器 @EnableResourceServer 的 Springboot 应用程序

@Configuration
@EnableResourceServer
public class SecurityConfig extends ResourceServerConfigurerAdapter 

    @Override
    public void configure(HttpSecurity http) throws Exception
        http.requestMatchers().antMatchers("/api/**")
                .and()
                .authorizeRequests().anyRequest().authenticated();
    

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception 
        resources.tokenServices(tokenServices()).resourceId("my-okta-resource-server-client-id");
    

    @Bean
    @Primary
    public DefaultTokenServices tokenServices() throws Exception 
        DefaultTokenServices tokenServices = new DefaultTokenServices();
        tokenServices.setTokenStore(tokenStore());
        return tokenServices;
    

    @Bean
    public TokenStore tokenStore() throws Exception 
       return new JwkTokenStore("https://my-org.oktapreview.com/oauth2/my-auth-server/v1/keys");
    

通过此设置,我可以使用JwkTokenStore 实现验证JWT 令牌是否正常(它在内部使用JwkVerifyingJwtAccessTokenConverter 从提供的密钥uri 中验证Json Web Keyset)。但是我无法将其配置为任一

    为其创建特定的 JWT 声明以创建 Authentication。它只查看 user_name 声明,我想在那里使用电子邮件或其他声明。 注入自定义用户详细信息服务。封装UserDetailsServiceDefaultUserAuthenticationConverter 被深深嵌入其中。这我需要在单独的休息服务中查找用户设置的权限。

Spring-security-oauth2 的 JWK 相关实现似乎已关闭,大多数 JWKs 验证相关类未公开。 什么是利用JwkTokenStore 提供的令牌验证的好方法,并且还能够在其中拥有您自己的用户详细信息以加载权限。

正在使用的软件版本: Springboot 1.5.2.RELEASE,spring-security-core:4.2.3,spring-security-oauth2:2.0.14,

【问题讨论】:

仅供参考:Spring 对 OAuth 和 OpenID Connect 的支持分布在多个项目中,现在正在被重写并整合到最新版本的 Spring Security 中。最新版本是 5.0.0.M2 在此处查看详细信息:github.com/spring-projects/spring-security/issues/3907 我已经在使用更新的软件版本,Spring security 4.2,它支持 open-id-connect 和 oauth2 实现。 Spring Security 4.2 仅包含对 OpenID 2.0 的支持,这是该标准的先前版本。 OpenID Connect 是新版本,直到 Spring Security 5.0(仍在开发中)才被 Spring 支持。 OAuth 故事传播到 Spring Boot、Spring Security、Spring Security OAuth、Spring Social 等。现在所有这些都被重写并整合到 Spring Security 5.0 中。因此,如果您需要 OpenID Connect,则必须使用 Spring Security 5.0。如果您只需要 OAuth,那么您可以根据需要利用已经提到的项目。 我也有同样的挑战。阿米特,你找到解决办法了吗?你切换到 Spring Security 5 了吗? 是的 Bernd,我现在在 Springboot2/Spring5 上,还能够提取自定义声明以及增强安全上下文以通过单独的服务调用添加角色。 【参考方案1】:

您应该使用所谓的DefaultAccessTokenConverter 来提取这些额外的声明并将其添加到OAuth2Authentication 对象中。

您可以将@Autowire CustomAccessTokenConverter 放入您的ResourceServerConfiguration 类,然后将其设置为您的JwtTokenStore() 配置。

资源服务器配置:

@Autowired
private CustomAccessTokenConverter yourCustomAccessTokenConverter;

@Override
public void configure(final ResourceServerSecurityConfigurer config) 
    config.tokenServices(tokenServices()).resourceId(resourceId);


@Bean
@Primary
public DefaultTokenServices tokenServices() 
    final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
    defaultTokenServices.setTokenStore(jwkTokenStore());
    return defaultTokenServices;


@Bean
public TokenStore jwtTokenStore() throws Exception 
   return new JwkTokenStore("https://my-org.oktapreview.com/oauth2/my-auth-server/v1/keys", accessTokenConverter());


@Bean
public JwtAccessTokenConverter accessTokenConverter() 
    JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
    converter.setAccessTokenConverter(yourCustomAccessTokenConverter);
    return converter;

可以配置 CustomAccessTokenConverter,以便在此处提取自定义声明。

CustomAccessTokenConverter:

@Component
public class CustomAccessTokenConverter extends DefaultAccessTokenConverter 

    @Override
    public OAuth2Authentication extractAuthentication(Map<String, ?> claims) 
        OAuth2Authentication authentication = super.extractAuthentication(claims);
        authentication.setDetails(claims);
        return authentication;
    

之后,您应该能够通过 OAuth2Authentication 对象访问声明。

【讨论】:

问题是 JwtTokenStore (来自您的回答)没有使用 jwk 来验证令牌(您必须自己实现)。 JwkTokenStore(由 OP 提到)可以,但不允许任何自定义(不能使用自定义 JwtAccessTokenConverter)。因此,您必须在重新发明***或不使用自定义权限之间做出选择。似乎网络上的很多资源只是选择使用 JwtTokenStore,并使用静态密钥而不是 jwk(这反过来意味着没有密钥轮换和糟糕的安全实践,或者停机时间和运营开销)。

以上是关于spring-security-oauth2 JwkTokenStore 与自定义用户详细信息服务的主要内容,如果未能解决你的问题,请参考以下文章

spring-security-oauth2中的HttpSecurity配置问题

如何处理 spring-security-oauth2 的版本升级?

spring-security-oauth2 替代品

Spring-Security-Oauth2:默认登录成功 url

spring-security-oauth2 2.0.7 刷新令牌 UserDetailsS​​ervice 配置 - UserDetailsS​​ervice 是必需的

spring-security-oauth2注解详解