集成Microsoft Entra ID到SPA与ASP.NET Core Web API:作用域与用户声明解析
关于Microsoft Entra ID集成Svelte SPA与ASP.NET Core Web API的权限问题解答
1. API作用域的功能:应用级+用户级的双重管控
API作用域(比如你定义的AdminTool.Read)核心是声明API资源的访问权限范围,它同时支持应用级和用户级的管控:
- 应用级控制:用来限定哪些客户端应用(比如你的Svelte SPA)有权请求这个权限,同时API端通过校验令牌中的
scp声明,确保只有携带该作用域的请求才能访问对应API接口。 - 用户级控制:Entra ID只会给被授权的用户/用户组颁发包含该作用域的令牌——你需要在Entra ID中给用户或组分配该作用域的权限,用户才能在登录时获取到带该作用域的令牌。所以实际落地时,作用域既管“哪个应用能访问”,也管“哪个用户能通过应用访问”。
你的当前配置中,API拒绝不带AdminTool.Read的请求,就是应用级的访问校验;而用户能拿到带这个作用域的令牌,前提是你已经在Entra ID里给该用户授权了这个权限,这就是用户级的管控。
2. 实现动态用户专属权限的方案
方案一:动态管理已定义的自定义作用域
如果想用类似Dashboard.Read的专属作用域,步骤如下:
- 先在Entra ID的「暴露API」中静态定义该作用域——这是必须的,因为作用域属于API资源的一部分,Entra ID需要识别这个权限声明。
- 通过Graph API动态给用户/组分配或移除该作用域的权限:
- 调用
POST /users/{user-id}/appRoleAssignments(用户)或POST /groups/{group-id}/appRoleAssignments(组)接口,传入该作用域对应的appRoleId(每个自定义作用域会自动生成对应的appRole)。
- 调用
- 前端请求令牌时带上
Dashboard.Read作用域,API端校验令牌的scp声明即可。
方案二:无需静态定义作用域的动态权限(推荐用应用角色)
如果不想在「暴露API」里静态定义权限,推荐用Entra ID的应用角色(App Roles):
- 在你的Entra ID应用注册中,直接定义App Roles(比如
Dashboard.Read、Order.Write等),不需要在「暴露API」中配置。 - 通过Graph API动态给用户/组分配或移除这些角色:同样调用
appRoleAssignments相关接口。 - 用户登录后,令牌中会包含
roles声明,API端只需校验该声明即可实现权限管控。
最佳实践
- 粗粒度权限用角色,细粒度权限用后端数据库:应用角色适合模块级的粗粒度权限(比如管理员、普通用户);如果要实现资源级的细粒度权限(比如用户只能查看自己创建的仪表盘),不要依赖Entra ID的权限声明,而是在API端通过用户的
oid(令牌中的对象ID)查询后端的权限数据库来校验。 - 优先用组分配权限:尽量给用户组分配角色/作用域,再把用户加入组,减少单个用户的权限管理成本。
- 权限变更后需重新登录:令牌是静态的,权限变更后用户需要重新登录才能获取包含新权限的令牌。
- 避免过度定义权限:不要为每个细粒度操作都定义作用域或角色,尽量合并为合理的权限组,降低管理复杂度。
内容的提问来源于stack exchange,提问作者nop
相关产品推荐
相关产品推荐

