POST请求Query Usage接口时Azure AD Bearer令牌未授权问题
问题根因
返回401是访问令牌的受众(aud)声明不匹配导致的:当前MSAL登录流程默认拿到的令牌,是颁发给你自己的Angular客户端应用的(错误信息里的guid值就是你Angular应用在Azure AD中的客户端ID),而调用Azure资源管理类接口(包括费用查询的Query Usage接口),要求令牌的受众必须是Azure资源管理器服务终结点,也就是https://management.azure.com/。
修复步骤
- 先配置Azure AD应用权限
进入Azure AD中你Angular客户端对应的应用注册页面,打开「API权限」板块:- 点击「添加权限」,选择「Azure 服务管理(Azure Resource Manager)」
- 勾选
user_impersonation委托权限,完成添加后如果是租户内应用,点击「授予管理员同意」完成权限配置
- 调整MSAL拦截器配置,给Azure管理接口绑定正确的权限范围
在Angular的MSAL初始化配置中,配置受保护资源映射,将指向Azure管理接口的请求和对应scope绑定,参考代码:
// MSAL实例工厂配置 export function MSALInstanceFactory(): IPublicClientApplication { return new PublicClientApplication({ auth: { clientId: '替换为你的Angular客户端应用ID', authority: 'https://login.microsoftonline.com/替换为你的Azure AD租户ID', redirectUri: '替换为你的前端应用重定向地址' }, cache: { cacheLocation: 'localStorage' } }); } // MSAL拦截器配置 export function MSALInterceptorConfigFactory(): MsalInterceptorConfiguration { const protectedResourceMap = new Map<string, Array<string>>(); // 匹配Azure管理接口的请求,绑定对应权限范围 protectedResourceMap.set('https://management.azure.com/*', [ 'https://management.azure.com/user_impersonation' ]); return { interactionType: InteractionType.Redirect, protectedResourceMap }; }
- 调用接口前主动获取对应资源的访问令牌
不要直接使用loginRedirect流程默认返回的令牌,调用费用查询接口前,通过静默获取接口拿对应scope的访问令牌,再放到请求头中,参考代码:
async queryAzureCost() { const tokenReq = { scopes: ['https://management.azure.com/user_impersonation'] }; try { const tokenRes = await this.msalService.acquireTokenSilent(tokenReq).toPromise(); const validAccessToken = tokenRes.accessToken; // 将validAccessToken以`Bearer ${validAccessToken}`的格式放到请求头Authorization字段,再发起POST请求即可 } catch (e) { // 静默获取令牌失败时,触发交互式获取 this.msalService.acquireTokenRedirect(tokenReq); } }
你在Postman中能调用成功,本质是Postman请求令牌时指定的资源值就是
https://management.azure.com/,拿到的令牌aud字段和接口要求匹配,和上述配置逻辑一致。
- 校验方式:拿到令牌后可以用JWT解析工具查看令牌 payload 中的
aud字段,如果值为https://management.azure.com,就说明令牌符合接口要求,不会再报受众不匹配的错误。
内容的提问来源于stack exchange,提问作者David Gutiérrez
相关产品推荐
相关产品推荐

