You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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}/
  • 确认令牌完整性
    检查传递的令牌是否为完整的三段式结构(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);
}

额外说明

  1. 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。
  2. 依赖版本:你的java-jwt和jwks-rsa版本兼容,无需调整,但建议定期更新到稳定版本。

内容的提问来源于stack exchange,提问作者Bas Kuis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 17:24:56