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

如何用原生JavaScript无第三方库验证OAuth 2.0令牌

纯原生JavaScript实现Azure AD OAuth 2.0令牌校验方案

完全不依赖MSAL或第三方库的前提下,有三种成熟可行的实现路径,你可以根据自己的部署场景(服务端/前端SPA)和性能要求选择:

方案1:调用官方令牌自省端点(服务端场景首选,实现成本最低)

这个方案完全不需要你处理签名验证、公钥轮换这类底层逻辑,直接调用微软身份平台标准的RFC 7662自省端点完成校验:

  • 端点格式:https://login.microsoftonline.com/{你的Azure AD租户ID}/oauth2/v2.0/introspect
  • 请求规则:以application/x-www-form-urlencoded格式POST提交参数,需要带你应用注册时拿到的client_id、client_secret,以及待校验的令牌
  • 原生JS实现示例:
async function validateTokenViaIntrospect(accessToken, tenantId, clientId, clientSecret) {
  const reqParams = new URLSearchParams();
  reqParams.append('token', accessToken);
  reqParams.append('client_id', clientId);
  reqParams.append('client_secret', clientSecret);

  const res = await fetch(`https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/introspect`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: reqParams
  });
  const data = await res.json();
  // 返回结果中active字段为true即代表令牌有效,同时会返回令牌的过期时间、作用域、所属用户等元信息
  return data.active === true;
}
  • 适用限制:仅适合服务端场景,client_secret必须存储在服务端,绝对不能写到前端代码里,否则会泄露应用凭证。

方案2:本地离线校验(前端SPA场景首选,无额外网络开销)

Azure AD签发的OAuth 2.0令牌(id_token、access_token)都是标准JWT格式,你可以用浏览器/Node.js原生支持的Web Crypto API完成本地校验,不需要发请求到微软服务:

  • 校验流程分三步:
    • 基础声明校验:先解码JWT的Payload部分,校验令牌是否在有效期内(对比exp过期时间戳、nbf生效时间戳和当前时间),校验aud受众字段是否为你自己的应用Client ID,校验iss签发者字段是否匹配你的租户地址,先过滤掉明显无效的令牌
    • 拉取签名公钥:从你租户的公开元数据端点拉取当前在用的签名公钥列表,公钥轮换频率很低,本地缓存24小时即可,不需要每次校验都拉取
    • 签名校验:用Web Crypto API导入对应公钥,校验JWT的签名是否合法,这一步是核心,跳过的话会存在伪造令牌绕过的风险
  • 无依赖JWT解析+基础校验代码示例:
// 解析JWT结构,不需要第三方库
function parseJwt(token) {
  const [headerSeg, payloadSeg] = token.split('.');
  const base64UrlDecode = (seg) => {
    const base64 = seg.replace(/-/g, '+').replace(/_/g, '/');
    const pad = base64.length % 4 ? '='.repeat(4 - (base64.length % 4)) : '';
    return JSON.parse(atob(base64 + pad));
  };
  return {
    header: base64UrlDecode(headerSeg),
    payload: base64UrlDecode(payloadSeg)
  };
}

// 基础声明校验
function checkTokenClaims(payload, clientId, tenantId) {
  const currentTs = Math.floor(Date.now() / 1000);
  if (payload.exp < currentTs) return false; // 令牌已过期
  if (payload.nbf > currentTs) return false; // 令牌尚未生效
  if (payload.aud !== clientId) return false; // 令牌不是发给当前应用的
  if (!payload.iss.includes(tenantId)) return false; // 令牌不是对应租户签发的
  return true;
}
  • 注意:签名校验部分直接用原生crypto.subtle.verify接口实现RS256签名验证即可,不需要引入任何第三方加密库。

方案3:受保护接口反向校验(轻量场景适用)

如果你本身就需要用令牌调用微软Graph或自有受保护接口,可以直接用待校验的令牌请求轻量接口,通过响应状态判断令牌有效性:

  • 最常用的检测端点是微软Graph的/me接口,只需要令牌带基础的User.Read权限即可调用,不需要额外配置
  • 实现示例:
async function validateTokenViaApiCall(accessToken) {
  try {
    const res = await fetch('https://graph.microsoft.com/v1.0/me', {
      headers: { 'Authorization': `Bearer ${accessToken}` }
    });
    return res.ok; // 状态码200代表令牌有效,401代表令牌无效/过期
  } catch (err) {
    return false;
  }
}
  • 适用限制:每次校验会产生一次网络请求,受接口限流规则约束,适合校验频率不高的场景。

避坑提醒:不要只解码JWT的Payload做时间、声明校验就判定令牌有效,必须完成签名校验或者调用官方端点确认,否则攻击者可以构造任意内容的假令牌绕过校验逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 01:21:39