JWToken 无效:孩子是必需的 JOSE Header
Invalid JWToken: kid is a required JOSE Header
我正在尝试使用此 guide 作为参考,使用 SpringBoot 实现 Oauth2 授权服务器。
我的密钥库只有一个密钥。我已经成功地创建了一个 JWToken(我可以在 jwt.io 上查看)。
我也有一个测试资源服务器。当我尝试访问任何端点时,我收到以下消息:
{
"error": "invalid_token",
"error_description": "Invalid JWT/JWS: kid is a required JOSE Header"
}
令牌确实没有孩子 header 但我不知道如何添加它。我只能使用 TokenEnchancer 将数据添加到它的有效负载中。看来我也不是第一个with this issue.
有什么方法可以添加这个 header 或者至少在资源服务器上忽略它?
我设法通过更改用于识别 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 配置指向具有单个键的端点。
我一直在写一篇可能对您有所帮助的文章:
https://www.baeldung.com/spring-security-oauth2-jws-jwk
所以,要配置一个Spring安全OAuth授权服务器来添加一个JWTkidheader,你可以按照4.9节的步骤操作:
- 创建一个新的 class 扩展 JwtAccessTokenConverter
- 在构造函数中:
- 使用您一直使用的相同方法配置 parent class
- 使用您正在使用的签名密钥Signerobject
- 覆盖编码方法。实现将与 parent 相同,唯一的区别是您在创建字符串令牌时还将传递自定义 headers
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;
}
}
- 然后,当然,使用这个转换器创建一个 bean:
@Bean
public JwtAccessTokenConverter accessTokenConverter(KeyPair keyPair) {
return new JwtCustomHeadersAccessTokenConverter(keyPair);
}
这里我使用了 KeyPair 实例来获取签名密钥并配置转换器(基于文章的示例),但您可以根据自己的配置进行调整。
在文章中我也解释了Spring Security OAuth Authentication Server 提供的相关端点。
此外,关于@Ortomala Lokni 的评论,我不希望 Spring Security OAuth 此时添加任何新功能。作为替代方案,您可能可以等待查看 Spring 安全的授权服务器功能,计划在 5.3.0
中发布
我正在尝试使用此 guide 作为参考,使用 SpringBoot 实现 Oauth2 授权服务器。
我的密钥库只有一个密钥。我已经成功地创建了一个 JWToken(我可以在 jwt.io 上查看)。
我也有一个测试资源服务器。当我尝试访问任何端点时,我收到以下消息:
{
"error": "invalid_token",
"error_description": "Invalid JWT/JWS: kid is a required JOSE Header"
}
令牌确实没有孩子 header 但我不知道如何添加它。我只能使用 TokenEnchancer 将数据添加到它的有效负载中。看来我也不是第一个with this issue.
有什么方法可以添加这个 header 或者至少在资源服务器上忽略它?
我设法通过更改用于识别 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 配置指向具有单个键的端点。
我一直在写一篇可能对您有所帮助的文章: https://www.baeldung.com/spring-security-oauth2-jws-jwk
所以,要配置一个Spring安全OAuth授权服务器来添加一个JWTkidheader,你可以按照4.9节的步骤操作:
- 创建一个新的 class 扩展 JwtAccessTokenConverter
- 在构造函数中:
- 使用您一直使用的相同方法配置 parent class
- 使用您正在使用的签名密钥Signerobject
- 覆盖编码方法。实现将与 parent 相同,唯一的区别是您在创建字符串令牌时还将传递自定义 headers
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;
}
}
- 然后,当然,使用这个转换器创建一个 bean:
@Bean
public JwtAccessTokenConverter accessTokenConverter(KeyPair keyPair) {
return new JwtCustomHeadersAccessTokenConverter(keyPair);
}
这里我使用了 KeyPair 实例来获取签名密钥并配置转换器(基于文章的示例),但您可以根据自己的配置进行调整。
在文章中我也解释了Spring Security OAuth Authentication Server 提供的相关端点。
此外,关于@Ortomala Lokni 的评论,我不希望 Spring Security OAuth 此时添加任何新功能。作为替代方案,您可能可以等待查看 Spring 安全的授权服务器功能,计划在 5.3.0
中发布