Java应用验证Azure AD JWT令牌时签名验证失败求助
Azure AD JWT签名验证失败排查与解决
核心排查点
- 匹配签名算法与令牌头部的
alg字段
解码JWT后,查看头部的alg值(比如RS256),仅使用对应算法验证,无需尝试所有RSA算法,多余尝试会干扰问题定位。 - 对齐令牌版本与密钥端点
你用Python ADAL获取的是Azure AD v1端点令牌,但Java代码中使用了v2版本的密钥端点。两者不匹配会导致获取的公钥与签名用密钥不一致:- v1令牌对应密钥端点:
https://login.microsoftonline.com/{tenant-id}/discovery/keys - v1令牌颁发者格式:
https://sts.windows.net/{tenant-id}/
- v1令牌对应密钥端点:
- 确认令牌完整性
检查传递的令牌是否为完整的三段式结构(header.payload.signature),无换行、空格或截断。 - 验证受众与颁发者(可选但推荐)
即使签名验证通过,也需要确认aud(受众)是否为你的Java应用Client ID或目标资源ID,iss(颁发者)是否与Azure AD租户一致,这能避免无效令牌通过验证。
修正后的Java验证代码
boolean validated = false; try { String token = tokenBody.token; DecodedJWT jwt = JWT.decode(token); log.info("JWT Key ID: {}", jwt.getKeyId()); log.info("JWT Algorithm: {}", jwt.getAlgorithm()); // 使用v1版本密钥端点,匹配ADAL获取的令牌 JwkProvider provider = new UrlJwkProvider(new URL("https://login.microsoftonline.com/tenant-id-12312-123-123-123/discovery/keys")); Jwk jwk = provider.get(jwt.getKeyId()); RSAPublicKey publicKey = (RSAPublicKey) jwk.getPublicKey(); // 根据令牌头部的alg选择对应算法 Algorithm algorithm; switch (jwt.getAlgorithm()) { case "RS256": algorithm = Algorithm.RSA256(publicKey, null); break; case "RS384": algorithm = Algorithm.RSA384(publicKey, null); break; case "RS512": algorithm = Algorithm.RSA512(publicKey, null); break; default: throw new IllegalArgumentException("Unsupported algorithm: " + jwt.getAlgorithm()); } // 构建JWT验证器,添加颁发者和受众验证(按需启用) JWTVerifier verifier = JWT.require(algorithm) // 验证颁发者,替换为你的租户对应的v1颁发者地址 .withIssuer("https://sts.windows.net/tenant-id-12312-123-123-123/") // 验证受众,替换为你的应用Client ID或目标资源ID(比如https://graph.microsoft.com) // .withAudience("https://graph.microsoft.com") .build(); // 执行完整验证 verifier.verify(jwt); validated = true; log.info("JWT signature verified successfully"); } catch (MalformedURLException e) { log.error("Invalid JWKS URL", e); } catch (JwkException e) { log.error("Failed to retrieve public key from JWKS", e); } catch (SignatureVerificationException e) { log.error("Signature verification failed", e); } catch (Exception e) { log.error("JWT verification failed", e); }
额外说明
- ADAL vs MSAL:ADAL是Azure AD v1版本的SDK,MSAL对应v2版本。如果后续切换到MSAL获取令牌,需要同步将密钥端点改为v2版本
https://login.microsoftonline.com/{tenant-id}/discovery/v2.0/keys,颁发者改为https://login.microsoftonline.com/{tenant-id}/v2.0。 - 依赖版本:你的
java-jwt和jwks-rsa版本兼容,无需调整,但建议定期更新到稳定版本。
内容的提问来源于stack exchange,提问作者Bas Kuis
相关产品推荐
相关产品推荐

