MSAL loginPopup报范围不存在错误,SPA调用WebAPI遭授权拒绝
首先帮你拆解下当前遇到的问题,结合你的代码和Azure AD配置来逐一解答:
疑问1:错误中的资源ID 00000003-0000-0000-c000-000000000000 是什么?
这个ID是Microsoft Graph的内置应用ID,是Azure AD里预定义的服务资源ID。当你在MSAL的请求中只指定了scopes: ["access_as_user"]但没有明确关联对应的目标资源时,MSAL会默认将请求的资源指向Microsoft Graph,所以错误提示里会显示Graph的资源ID,而你的access_as_user是属于自己WebAPI的scope,自然在Graph里不存在,导致了AADSTS650053错误。
疑问2:Azure配置和客户端代码中的错误?
核心问题出在scope的格式不正确,以及对应的权限配置验证:
代码层面的错误:
你的requestObj里的scope只写了access_as_user,MSAL无法识别这个scope属于你的WebAPI,默认会绑定到Graph。正确的scope格式应该是WebAPI的应用ID URI + scope名称,比如:
var requestObj = { scopes: ["https://my.tenant/TodoListService-NativeDotNet/access_as_user"] };
这里的https://my.tenant/TodoListService-NativeDotNet就是你在Azure AD中注册WebAPI时设置的应用ID URI(可以在WebAPI的应用注册→“暴露API”页面找到)。
Azure配置层面需要检查的点:
- WebAPI的scope配置:确认在WebAPI的应用注册→“暴露API”中,已经正确创建了
access_as_user的scope,并且状态为“已启用”,应用ID URI和你代码中使用的一致。 - 客户端应用的权限配置:在客户端SPA的应用注册→“API权限”中,已经添加了WebAPI的
access_as_user权限,并且点击了“授予管理员同意”(如果是单租户应用,必须由管理员完成此操作;多租户应用可由用户自行同意)。
另外,当你换成user.read时,这个是Graph的内置scope,所以能拿到令牌,但令牌的受众(aud字段)是Graph的资源ID,而你的WebAPI只接受受众为自己应用ID/URI的令牌,所以调用API时会返回Authorization has been denied for this request.。
疑问3:CORS是否是问题?
从你描述的情况来看,当前核心问题不是CORS:
- 你遇到的
AADSTS650053错误发生在令牌获取阶段,和CORS无关; - 换成
user.read后API调用的错误是因为令牌受众不匹配,不是CORS错误(如果是CORS问题,浏览器会直接提示跨域相关的错误信息)。
你已经在服务端配置了CORS允许规则,这部分暂时不需要调整。
修复步骤总结:
- 登录Azure门户,找到你的WebAPI应用注册,进入“暴露API”页面,复制完整的应用ID URI(比如
https://my.tenant/TodoListService-NativeDotNet); - 修改客户端代码中的
requestObj,将scope改为[应用ID URI/access_as_user]; - 确认客户端应用已添加WebAPI的
access_as_user权限并完成同意授权; - 重新测试
getTodos函数,此时获取到的令牌受众应该是你的WebAPI的应用ID/URI,调用API即可成功。
内容的提问来源于stack exchange,提问作者user0710192002

