【问题标题】:Invalid JWToken: kid is a required JOSE Header无效的 JWToken:kid 是必需的 JOSE 标头
【发布时间】:2019-09-03 16:25:04
【问题描述】:

我正在尝试使用此guide 作为参考,使用 SpringBoot 实现 Oauth2 授权服务器。

我的密钥库只有一个密钥。我已经成功创建了一个 JWToken(我可以在 jwt.io 上查看)。

我还有一个测试资源服务器。当我尝试访问任何端点时,我会收到以下消息:

{
  "error": "invalid_token",
  "error_description": "Invalid JWT/JWS: kid is a required JOSE Header"
}

令牌确实没有孩子头,但我不知道如何添加它。我只能使用 TokenEnchancer 将数据添加到其有效负载中。看来我不是第一个with this issue

有什么方法可以添加这个标头,或者至少在资源服务器上忽略它?

【问题讨论】:

标签: spring-boot spring-security jwt spring-security-oauth2


【解决方案1】:

我设法解决了这个问题,更改了用于识别客户端将检索 pubkey 的 URL 的参数。

在 application.properties 上,而不是:

security.oauth2.resource.jwk.key-set-uri=http://{auth_server}/.well-known/jwks.json

我用过:

security.oauth2.resource.jwt.key-uri=http://{auth_server}/oauth/token_key

如果我理解正确的话,key-set-uri 配置指向一个端点,它提供一组键,并且需要一个孩子。另一方面,key-uri 配置指向具有单个密钥的端点。

【讨论】:

    【解决方案2】:

    我一直在撰写一篇可能对您有所帮助的文章: https://www.baeldung.com/spring-security-oauth2-jws-jwk

    所以,要配置一个 Spring Security OAuth 授权服务器来添加一个 JWT kid 头,你可以按照 4.9 节的步骤:

    1. 创建一个扩展 JwtAccessTokenConverter 的新类
    2. 在构造函数中:
      1. 使用您一直使用的相同方法配置父类
      2. 使用您正在使用的签名密钥获取 Signer 对象
    3. 覆盖编码方法。实现将与父实现相同,唯一的区别是您还将在创建字符串令牌时传递自定义标头
    public class JwtCustomHeadersAccessTokenConverter extends JwtAccessTokenConverter {
    
        private JsonParser objectMapper = JsonParserFactory.create();
        final RsaSigner signer;
    
        public JwtCustomHeadersAccessTokenConverter(KeyPair keyPair) {
            super();
            super.setKeyPair(keyPair);
            this.signer = new RsaSigner((RSAPrivateKey) keyPair.getPrivate());
        }
    
        @Override
        protected String encode(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
            String content;
            try {
                content = this.objectMapper.formatMap(getAccessTokenConverter().convertAccessToken(accessToken, authentication));
            } catch (Exception ex) {
                throw new IllegalStateException("Cannot convert access token to JSON", ex);
            }
            Map<String, String> customHeaders = Collections.singletonMap("kid", "my_kid");
            String token = JwtHelper.encode(content, this.signer, this.customHeaders)
                .getEncoded();
            return token;
        }
    }
    
    1. 然后,当然,使用这个转换器创建一个 bean:
    @Bean
    public JwtAccessTokenConverter accessTokenConverter(KeyPair keyPair) {
        return new JwtCustomHeadersAccessTokenConverter(keyPair);
    }
    

    这里我使用了一个 KeyPair 实例来获取签名密钥并配置转换器(基于文章的示例),但您可以根据自己的配置进行调整。

    在文章中我还解释了 Spring Security OAuth Authentication Server 提供的相关端点。

    另外,关于@Ortomala Lokni 的评论,我不希望 Spring Security OAuth 在这一点上添加任何新功能。作为替代方案,您可能可以等待查看 Spring Security 的 Authorization Server 功能,计划在 5.3.0 发布。

    【讨论】:

      猜你喜欢
      • 2023-04-03
      • 2010-10-11
      • 2021-01-24
      • 1970-01-01
      • 2021-09-18
      • 2017-03-27
      • 1970-01-01
      • 2018-02-03
      • 1970-01-01
      相关资源
      最近更新 更多