Spring Security使用private_key_jwt时出现invalid_client错误如何解决
问题原因
- 核心问题出在
ClientRegistration构建代码的语法错误:clientAuthenticationMethod(ClientAuthenticationMethod.PRIVATE_KEY_JWT)行末尾多了多余的分号,导致该配置未被加入构建链路,ClientRegistration最终使用的还是默认的client_secret_basic认证方式,因此NimbusJwtClientAuthenticationParametersConverter不会触发jwkResolver执行,也不会生成private_key_jwt要求的认证参数。 - 次要问题:当前jwk生成逻辑使用随机UUID作为kid,和你在认证服务商后台上传公钥时绑定的kid不匹配,即使第一步修复后也会出现签名校验失败问题。
可行解决方案
1. 修复ClientRegistration配置语法
删除clientAuthenticationMethod配置行末尾的多余分号,确保认证方式配置生效:
private ClientRegistration idPortenClientRegistration() { return ClientRegistrations .fromIssuerLocation("the endpoint") .clientId("the client id") .registrationId("idporten") .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) .redirectUri("the redirect url") .scope(Arrays.asList("the scopes")) .userNameAttributeName(IdTokenClaimNames.SUB) .clientName("idporten") // 移除本行末尾多余分号 .clientAuthenticationMethod(ClientAuthenticationMethod.PRIVATE_KEY_JWT) .build(); }
2. 修正JWK的kid配置
将随机生成的kid替换为你在认证服务商客户端后台上传公钥时配置的对应kid值:
private Function<ClientRegistration, JWK> jwkResolver = (clientRegistration) -> { if (clientRegistration.getClientAuthenticationMethod().equals(ClientAuthenticationMethod.PRIVATE_KEY_JWT)) { JKSKeyManager keyManager = getApplicationContext().getBean("keyManager", JKSKeyManager.class); try { RSAPublicKey publicKey = (RSAPublicKey) keyManager.getPublicKey("idporten1"); KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) keyManager.getKeyStore() .getEntry("idporten1", new KeyStore.PasswordProtection(keyEntryPassword1.toCharArray())); RSAPrivateKey privateKey = (RSAPrivateKey) pkEntry.getPrivateKey(); // 替换为认证端注册的实际kid,不要用随机UUID return new RSAKey.Builder(publicKey).privateKey(privateKey).keyID("你在服务商后台配置的公钥kid").build(); } catch (NoSuchAlgorithmException | UnrecoverableEntryException | KeyStoreException e) { logger.error("Failed to configure jwkResolver: " + e.getMessage(), e); } } return null; };
3. 可选验证步骤
在请求转换器中添加日志,打印发往token端点的完整请求参数,确认包含client_assertion和client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer两个必填认证参数。
内容的提问来源于stack exchange,提问作者Erlend Garåsen
相关产品推荐
相关产品推荐

