Java 无法将JWT刷新令牌作为参数传递
我正在尝试使用OAuth2的Spring Boot中的刷新令牌获取新的访问令牌。应该按照以下步骤执行: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":
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;
}