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

如何在Next.js TS API中验证AAD访问令牌?签名验证失败求助

解决Azure AD令牌在Next.js API中验证失败(invalid signature)的问题

问题排查与修复步骤

1. 修正JWKS URI地址

你现在用的JWKS URI带了appid参数,这会导致获取到的密钥不匹配。Azure AD的标准JWKS地址要根据你用的端点版本选择:

  • v2.0端点:https://login.microsoftonline.com/<你的租户ID>/discovery/v2.0/keys
  • v1.0端点:https://login.microsoftonline.com/<你的租户ID>/discovery/keys
    不用加appid参数,jwks-rsa库会自动根据令牌头部的kid匹配对应密钥。

2. 用jwks-rsa内置方法获取签名密钥

别自己手动拼接证书字符串,jwks-rsa的getSigningKey方法会自动处理密钥格式,避免格式错误导致签名验证失败。

3. 补充必要的验证参数

哪怕忽略过期时间,也得验证令牌的audience(你的Next.js API在Azure AD中的客户端ID)和issuer(签发者地址),否则可能验证的是其他应用的令牌。

4. 确认令牌类型与受众

确保Flutter客户端获取的是访问令牌(而非ID令牌),且令牌的aud字段值是你Next.js API的客户端ID,不是Flutter应用的客户端ID。

修正后的验证代码

import jwt, { VerifyOptions } from 'jsonwebtoken';
import jwksClient from 'jwks-rsa';

// 替换为你的租户ID和API客户端ID
const TENANT_ID = '<你的租户ID>';
const API_CLIENT_ID = '<你的Next.js API客户端ID>';
// 选择对应版本的JWKS URI
const JWKS_URI = `https://login.microsoftonline.com/${TENANT_ID}/discovery/v2.0/keys`;
// 签发者地址,v2.0用此格式,v1.0为https://sts.windows.net/${TENANT_ID}/
const ISSUER = `https://login.microsoftonline.com/${TENANT_ID}/v2.0`;

const client = jwksClient({
  jwksUri: JWKS_URI,
});

export default async function isValidToken(token: string): Promise<boolean> {
  try {
    // 解码令牌获取kid字段
    const decoded = jwt.decode(token, { complete: true });
    if (!decoded || !decoded.header?.kid) {
      console.log('令牌格式无效或缺少kid字段');
      return false;
    }

    // 通过kid获取对应签名密钥
    const key = await client.getSigningKey(decoded.header.kid);
    const publicKey = key.getPublicKey();

    const verifyOptions: VerifyOptions = {
      ignoreExpiration: true, // 调试阶段临时忽略过期,上线后建议关闭
      ignoreNotBefore: true,
      algorithms: ['RS256'],
      audience: API_CLIENT_ID, // 必须验证受众
      issuer: ISSUER // 必须验证签发者
    };

    // 执行令牌验证
    jwt.verify(token, publicKey, verifyOptions);
    console.log('令牌验证通过');
    return true;
  } catch (err) {
    console.log('令牌验证失败:', err);
    return false;
  }
}

额外检查项

  • 确认Flutter请求令牌时,scope参数包含你的API权限范围(例如api://<API客户端ID>/access_as_user)
  • 检查令牌的iss字段是否与你设置的ISSUER一致,可以手动解码令牌查看字段值
  • 确保Azure AD中API应用的「允许的令牌受众」包含你的API客户端ID

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 15:27:53