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

Azure MSAL-Browser结合Next.js调用API仅传递单个scope问题

问题根因

你观察到的现象不是Azure AD的逻辑异常,是@azure/msal-browser@2.x的令牌匹配规则和Azure AD本身的令牌设计共同导致的,核心规则如下:

  1. Azure AD 不支持为多个不同资源(即令牌的aud受众声明对应不同服务)签发同一张访问令牌,你自定义的API和Microsoft Graph是两个完全独立的资源,不可能出现在同一张访问令牌的受众里。
  2. MSAL Browser 2.x 版本在处理传入的scope数组时,如果数组包含跨资源的权限,会默认取第一个有效资源对应的scope所属的服务,从缓存中匹配或重新请求对应服务的访问令牌,其余跨资源的scope会被直接忽略。

你测试的所有结果都完全符合上述规则:

  • scopes = ['access']:第一个有效scope是你自定义API的access,返回的是发给你API的令牌,scope包含access,鉴权通过。
  • scopes = ['user.read']:第一个有效scope是Microsoft Graph的User.Read,返回的是发给Graph的令牌,aud值为Graph服务地址,和你API的预期受众不匹配,鉴权失败,令牌中携带的是Graph相关的基础委托权限。
  • scopes = ['access', 'user.read']:第一个有效scope是你自定义API的access,返回你API对应的令牌,跨资源的user.read被自动忽略,令牌scope仅包含access,鉴权通过。
  • scopes = ['user.read', 'access']:第一个有效scope是Graph的User.Read,返回Graph对应的令牌,aud不匹配导致鉴权失败。
  • scopes = ['profile', 'email', 'openid', 'access']:前三个是OIDC协议的基础身份scope,不对应独立业务资源,第一个有效业务资源scope是access,返回你API的令牌,鉴权通过。
修复方法

不需要调整Azure AD应用注册或服务端鉴权逻辑,只需要调整前端MSAL调用的scope传参规则即可:

  • 每次调用acquireTokenSilent、loginPopup、loginRedirect方法申请访问你自定义API的令牌时,将你自己API的自定义scope放在scope数组的第一位,不要把其他资源的scope放在自定义API scope之前。
  • 申请单张访问令牌时,保证传入的所有scope都属于同一个资源,不要把你自定义API的scope和Graph、其他第三方服务的scope混在同一次令牌请求中。
  • 服务端鉴权时必须增加aud(受众)声明校验,确认令牌是签发给你自己API的,不要仅校验scope字段,避免收到其他资源的令牌时出现鉴权逻辑漏洞。
API侧获取User.Read对应用户信息的实现方案

Azure AD不支持跨资源权限合并到同一张令牌,你无法在自定义API的访问令牌中携带Graph的User.Read权限,可根据业务场景二选一实现:

  • 方案一(推荐,安全性最高):后端使用OBO代理流换取Graph令牌。前端只需要正常传递带有access scope的自定义API访问令牌即可,后端校验令牌合法后,以该令牌为凭据向Azure AD申请访问Microsoft Graph的令牌,自主调用Graph的/me接口拉取需要的用户信息。该方案不需要给前端分配Graph权限,权限收敛在后端,风险最低。
  • 方案二:前端分两次独立申请令牌。前端第一次传入自定义API的scope数组,申请调用你后端接口需要的令牌;第二次单独传入['User.Read']作为scope,申请访问Graph的令牌,前端直接调用Graph接口拿到用户信息后,将需要的字段作为业务参数传给你的后端即可。该方案需要在Azure AD应用注册中给SPA客户端配置User.Read的委托权限,适合前端本身需要直接操作Graph能力的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 21:27:45