Spring Security 6中使用client_secret_jwt获取OAuth2令牌失败求助
Spring Security 6
client_secret_jwt 认证失败问题解决 核心问题:签名算法不匹配
从异常信息 Signed JWT rejected: Another algorithm expected, or no matching key(s) found 可以明确,你的客户端配置与JWT生成代码使用了不同的签名算法:
- 客户端注册时指定了
RS256(非对称RSA算法) - 但生成JWT时用了
HS256(对称HMAC算法)
这是导致认证失败的根本原因,以下是两种修复方案:
方案一:使用对称加密(HS256)
这种方式更简单,适合快速验证:
1. 修改客户端注册配置
将签名算法改为 HS256,并移除JWKS配置(HS算法无需公钥集):
@Bean public RegisteredClientRepository registeredClientRepository() { RegisteredClient registeredClient = RegisteredClient .withId(UUID.randomUUID().toString()) .clientId("client") .clientSecret("secret_secret_secret_secret_secret") .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_JWT) .clientSettings(ClientSettings.builder() // 改为HS256对称算法 .tokenEndpointAuthenticationSigningAlgorithm(SignatureAlgorithm.HS256) // 移除jwkSetUrl配置 .build()) .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS) .redirectUri("https://www.manning.com/authorized") .scope("CUSTOM") .build(); return new InMemoryRegisteredClientRepository(registeredClient); }
2. 保留现有JWT生成代码
你的getJWTToken方法已经使用了HS256签名,且密钥与客户端clientSecret一致,无需修改。
方案二:使用非对称加密(RS256)
如果需要更安全的非对称认证,按以下步骤调整:
1. 生成RSA密钥对
添加密钥生成逻辑:
private static RSAKey generateRsaKey() { try { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(2048); KeyPair keyPair = keyPairGenerator.generateKeyPair(); RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); return new RSAKey.Builder(publicKey) .privateKey(privateKey) .keyID(UUID.randomUUID().toString()) .build(); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } } private final RSAKey rsaKey = generateRsaKey();
2. 修改JWT生成代码
使用RSA私钥签名:
private String getJWTToken(String username) { String token = Jwts.builder() .subject(username) .issuer(username) .id(UUID.randomUUID().toString()) .audience().add("http://localhost:8080/oauth2/token").and() .issuedAt(new Date(System.currentTimeMillis())) .expiration(new Date(System.currentTimeMillis() + 600*1000)) // 使用RSA私钥和RS256算法签名 .signWith(rsaKey.toPrivateKey(), SignatureAlgorithm.RS256) .compact(); return token; }
3. 保留客户端注册配置
你的现有RegisteredClient配置已经指定了RS256和JWKS地址,无需修改(Spring Security会自动暴露/oauth2/jwks端点)。
验证请求
确保你的curl请求参数正确:
curl -X POST -v \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=client_credentials&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion=生成的JWT令牌" \ http://localhost:8080/oauth2/token
内容的提问来源于stack exchange,提问作者Vaibhav
相关产品推荐
相关产品推荐

