Java 无法将JWT刷新令牌作为参数传递

Java 无法将JWT刷新令牌作为参数传递,java,spring,spring-boot,spring-mvc,oauth-2.0,Java,Spring,Spring Boot,Spring Mvc,Oauth 2.0,我正在尝试使用OAuth2的Spring Boot中的刷新令牌获取新的访问令牌。应该按照以下步骤执行:POST:url/oauth/token?grant\u type=refresh\u token&refresh\u token=… 如果我使用InMemoryTokenStore,它可以正常工作,因为令牌很小,只包含数字/字母,但现在我使用的是JWT令牌,您可能知道它有3个不同的部分,可能会破坏代码 我用的是官方的 当我尝试访问上面的URL时,我收到以下消息: { "error":

我正在尝试使用OAuth2的Spring Boot中的刷新令牌获取新的访问令牌。应该按照以下步骤执行:
POST:url/oauth/token?grant\u type=refresh\u token&refresh\u token=…

如果我使用InMemoryTokenStore,它可以正常工作,因为令牌很小,只包含数字/字母,但现在我使用的是JWT令牌,您可能知道它有3个不同的部分,可能会破坏代码

我用的是官方的

当我尝试访问上面的URL时,我收到以下消息:

{
    "error": "invalid_token",
    "error_description": "Cannot convert access token to JSON"
}
如何在参数中传递JWT令牌?我试图在该消息上设置断点,以便查看实际参数是什么,但由于某种原因,它没有到达

/**
*授权服务器负责生成特定于客户端的令牌。
*更多信息可在此处找到:https://www.devglan.com/spring-security/spring-boot-security-oauth2-example.
*/
@配置
@EnableAuthorizationServer
公共类AuthorizationServerConfig扩展AuthorizationServerConfigurerAdapter{
@值(${user.oauth2.client id})
私有字符串clientId;
@值(${user.oauth2.client secret}”)
私有字符串clientSecret;
@值(${user.oauth2.accessTokenValidity}”)
私有整数有效性;
@值(${user.oauth2.refreshtTokenValidity}”)
私人有效性;
@自动连线
私有客户端详细信息服务客户端详细信息服务;
@自动连线
私人AuthenticationManager AuthenticationManager;
@自动连线
专用BCryptPasswordEncoder BCryptPasswordEncoder;
@凌驾
公共无效配置(ClientDetailsServiceConfigurer客户端)引发异常{
客户
.inMemory()
.withClient(客户端ID)
.secret(bCryptPasswordEncoder.encode(clientSecret))
.authorizedGrantTypes(“密码”、“授权码”、“刷新令牌”)
.scopes(“读”、“写”、“信任”)
.ResourceId(“api”)
.accessTokenValiditySeconds(accessTokenValidity)
.refreshTokenValiditySeconds(refreshTokenValidity);
}
@凌驾
public void configure(AuthorizationServerEndpointsConfigurer端点)引发异常{
端点
.authenticationManager(authenticationManager)
.tokenStore(tokenStore())
.userApprovalHandler(userApprovalHandler())
.accessTokenConverter(accessTokenConverter());
}
@豆子
公共用户ApprovalHandler用户ApprovalHandler(){
ApprovalStoreUserApprovalHandler userApprovalHandler=新ApprovalStoreUserApprovalHandler();
setApprovalStore(approvalStore());
setClientDetailsService(clientDetailsService);
setRequestFactory(新的DefaultOAuth2RequestFactory(clientDetailsService));
返回userApprovalHandler;
}
@豆子
公共令牌库令牌库(){
JwtTokenStore tokenStore=新的JwtTokenStore(accessTokenConverter());
setApprovalStore(approvalStore());
返回代币店;
}
@豆子
公共JwtAccessTokenConverter accessTokenConverter(){
最终RsaSigner签名者=新的RsaSigner(KeyConfig.getSignerKey());
JwtAccessTokenConverter=新的JwtAccessTokenConverter(){
私有JsonParser objectMapper=JsonParserFactory.create();
@凌驾
受保护的字符串编码(OAuth2AccessToken accessToken,OAuth2Authentication身份验证){
字符串内容;
试一试{
content=this.objectMapper.formatMap(getAccessTokenConverter().convertAccessToken(accessToken,身份验证));
}捕获(例外情况除外){
抛出新的IllegalStateException(“无法将访问令牌转换为JSON”,ex);
}
Map headers=newhashmap();
headers.put(“kid”,KeyConfig.VERIFIER\u KEY\u ID);
返回JwtHelper.encode(内容、签名者、标题).getEncoded();
}
};
转换器。设置信号器(信号器);
setVerifier(新的rsavifier(KeyConfig.getVerifierKey());
回流转换器;
}
@豆子
公共批准存储批准存储(){
返回新的InMemoryApprovalStore();
}
@豆子
公共JWKSet JWKSet(){
RSAKey.Builder=new RSAKey.Builder(KeyConfig.getVerifierKey())
.keyUse(keyUse.SIGNATURE)
.algorithm(JWSAlgorithm.RS256)
.keyID(KeyConfig.VERIFIER\u KEY\u ID);
返回新的JWKSet(builder.build());
}
}

我假设
无法将访问令牌转换为JSON
可能是由于令牌粘贴错误造成的

至于
无效的刷新令牌
,发生这种情况是因为
JwtTokenStore
读取刷新令牌时,它使用
InMemoryApprovalStore
验证作用域和吊销。但是,对于此实现,只有在通过
/oauth/authorize
URL(授权代码授予)由
ApprovalStoreUserApprovalHandler
进行授权的过程中,才会注册批准

特别是对于授权代码授予(授权\u Code),您希望进行此验证,以便在用户不知情的情况下,不会使用扩展范围调用刷新令牌请求。此外,还可以选择存储批准以备将来撤销

解决方案是使用所有资源所有者的
Approval
列表(静态或动态)填充
ApprovalStore
)。此外,您可能缺少设置用户详细信息服务
endpoints.userDetailsService(userDetailsService)
,该服务在刷新过程中使用

更新:

您可以验证这一点
@Bean
public ApprovalStore approvalStore() {
    InMemoryApprovalStore approvalStore = new InMemoryApprovalStore();
    Date expirationDate = Date.from(Instant.now().plusSeconds(3600));
    List<Approval> approvals = Stream.of("read", "write", "trust")
            .map(scope -> new Approval("admin", "trusted", scope, expirationDate,
                    ApprovalStatus.APPROVED))
            .collect(Collectors.toList());
    approvalStore.addApprovals(approvals);
    return approvalStore;
}