如何在Azure Entra ID中获取含多Scope的单一访问令牌
解决Azure Entra ID中无法同时获取自定义API与Graph API范围单一令牌的问题
核心原因解释
Azure Entra ID颁发的访问令牌(Access Token)的aud(受众)字段只能对应单个资源:
- Graph API的令牌受众是
https://graph.microsoft.com - 你的自定义Web API的令牌受众是
api://********-****-****-****-************
因此不存在同时包含两个不同资源范围的单一令牌,必须分别获取对应资源的令牌,各自用于访问对应的服务。
解决方案步骤
1. 调整React客户端的令牌获取逻辑
使用msal-react/msal-browser分别针对两个资源请求令牌:
- 获取Graph API令牌:
const graphTokenRequest = { scopes: ["User.Read", "Directory.ReadWrite.All", "User.Invite.All"], authority: "https://login.microsoftonline.com/你的租户ID" }; // 优先静默获取,失败则弹窗 const graphTokenResponse = await instance.acquireTokenSilent(graphTokenRequest) .catch(err => instance.acquireTokenPopup(graphTokenRequest)); - 获取自定义API令牌:
const apiTokenRequest = { scopes: ["api://********-****-****-****-************/Mes"], authority: "https://login.microsoftonline.com/你的租户ID" }; const apiTokenResponse = await instance.acquireTokenSilent(apiTokenRequest) .catch(err => instance.acquireTokenPopup(apiTokenRequest));
2. API端的权限验证处理
- MES模块:直接验证自定义API令牌的
scp字段是否包含Mes范围即可。 - User Management模块:
有两种处理方式:- 方式一:前端调用时同时携带自定义API令牌和Graph API令牌,API先验证自定义令牌的
Mes范围,再用Graph令牌调用Microsoft Graph API。 - 方式二:让Web API作为中间层,使用On-Behalf-Of(OBO)流程代表用户获取Graph API令牌。这种方式下前端只需要传递自定义API令牌,API内部通过OBO流程向Entra ID请求Graph令牌,避免前端直接处理多个令牌。
- 方式一:前端调用时同时携带自定义API令牌和Graph API令牌,API先验证自定义令牌的
3. 优化用户体验:增量授权
如果希望用户只需要一次同意所有权限,可以在登录请求中包含所有范围,这样用户首次登录时会一次性同意所有权限,后续获取令牌时无需重复授权:
const loginRequest = { scopes: [ "api://********-****-****-****-************/Mes", "User.Read", "Directory.ReadWrite.All", "User.Invite.All" ] }; instance.loginPopup(loginRequest);
注意:即使登录时请求了所有范围,仍然需要分别获取两个资源的令牌,只是用户授权流程简化了。
内容的提问来源于stack exchange,提问作者wasi hyder
相关产品推荐
相关产品推荐

