SpringBoot应用用JWT客户端断言遇AADSTS900144错误的排查解决
解决AADSTS900144错误:JWT客户端断言模式下client_id缺失问题
1. 检查自定义资源细节类的client_id配置
确保你的JwtOAuth2ProtectedResourceDetails类正确继承AuthorizationCodeResourceDetails,且配置Bean时显式设置clientId属性,不能仅添加断言相关配置。示例代码:
@Bean public JwtOAuth2ProtectedResourceDetails azureADResourceDetails() { JwtOAuth2ProtectedResourceDetails details = new JwtOAuth2ProtectedResourceDetails(); details.setClientId("your-client-id"); // 必须显式配置 details.setClientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_JWT); details.setTokenUri("https://login.microsoftonline.com/your-tenant-id/oauth2/v2.0/token"); // 补充JWT断言相关配置:如密钥库路径、密钥别名、密码等 return details; }
2. 修复OAuth2RestTemplate的参数组装逻辑
默认的OAuth2RestTemplate在JWT断言模式下可能存在参数遗漏问题,需自定义ClientCredentialsAccessTokenProvider强制将client_id放入请求体:
@Bean public OAuth2RestTemplate oAuth2RestTemplate(OAuth2ProtectedResourceDetails resourceDetails) { OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails); ClientCredentialsAccessTokenProvider provider = new ClientCredentialsAccessTokenProvider() { @Override protected void prepareRequest(AccessTokenRequest request, OAuth2ProtectedResourceDetails resource, MultiValueMap<String, String> form) { super.prepareRequest(request, resource, form); // 强制添加client_id到请求体,避免缺失 form.add("client_id", resource.getClientId()); } }; restTemplate.setAccessTokenProvider(provider); return restTemplate; }
3. 确认客户端认证方法配置匹配
根据你的签名方式,正确设置clientAuthenticationMethod:
- 若使用客户端密钥签名JWT,设置为
ClientAuthenticationMethod.CLIENT_SECRET_JWT - 若使用私钥签名JWT,设置为
ClientAuthenticationMethod.PRIVATE_KEY_JWT,同时配置密钥库相关参数:
details.setClientAuthenticationMethod(ClientAuthenticationMethod.PRIVATE_KEY_JWT); details.setJwtKeyStore(new ClassPathResource("your-keystore.jks")); details.setJwtKeyAlias("your-key-alias"); details.setJwtKeyPassword("your-key-password");
4. 调试请求体参数验证
添加请求拦截器打印实际发送的令牌请求体,确认client_id是否存在:
restTemplate.getInterceptors().add((request, body, execution) -> { if (request.getURI().toString().contains("/token")) { System.out.println("Token request body: " + new String(body, StandardCharsets.UTF_8)); } return execution.execute(request, body); });
如果打印结果无client_id,需重新调整令牌提供者的参数组装逻辑。
5. 对比Python脚本的请求参数
将Spring发送的请求参数与Python成功请求的参数逐一对比,确保client_id、grant_type、client_assertion_type、client_assertion等必填参数完全一致,注意授权码模式下grant_type为authorization_code,需同时携带code和redirect_uri。
内容的提问来源于stack exchange,提问作者Jack BeNimble
相关产品推荐
相关产品推荐

