基于Azure AD的服务授权:API路由权限控制方案咨询
好问题!针对你在Azure AD环境下对中心API(API X)做路由权限控制的需求,我推荐两种高效且符合Azure最佳实践的实现方式,比直接调用Graph API要简单可靠得多:
方案一:利用Azure AD应用角色(App Roles)实现细粒度权限控制
这是最直接的方案,能让Group B的API在请求API X时拿到带专属权限声明的JWT,完全不需要额外调用Graph API,完美匹配你“Group B令牌含额外声明”的理想状态。具体步骤如下:
在API X的AAD应用注册中定义应用角色
登录Azure门户,找到API X对应的应用注册,进入「应用角色」页面,点击「创建应用角色」:- 填写角色名称(比如
AccessSpecialStuff)和描述 - 「允许分配的类型」选择应用程序(因为是API之间的服务对服务调用,没有用户上下文,属于客户端凭据流场景)
- 保存角色配置
- 填写角色名称(比如
给Group B的API分配专属角色
找到Group B对应的API的应用注册(也就是它的服务主体),进入「权限」页面:- 点击「添加权限」→「我的API」,选择API X
- 在「应用权限」分类下找到刚才创建的
AccessSpecialStuff角色,添加权限 - 点击「授予管理员同意」(必须完成这一步,否则Group B的API拿不到带该角色的令牌)
- Group A的API只需要添加API X的基础应用权限(比如默认的
access_as_application),不需要分配AccessSpecialStuff角色
在API X中验证权限声明
API X收到请求时,解析JWT令牌的roles声明:- 若包含
AccessSpecialStuff,则允许访问/api/specialStuff/...路由 - 若没有该声明,直接返回403权限拒绝
- 若包含
举个ASP.NET Core的代码示例(用Microsoft.Identity.Web库):
// Program.cs中配置授权策略 builder.Services.AddAuthorization(options => { options.AddPolicy("SpecialStuffAccess", policy => policy.RequireClaim("roles", "AccessSpecialStuff")); }); // 给特殊路由绑定授权策略 app.MapGroup("/api/specialStuff") .RequireAuthorization("SpecialStuffAccess") .MapControllers();
方案二:利用AAD安全组声明控制权限
如果更倾向用AAD组来管理API集合,也可以通过配置让令牌自动携带组信息,同样不需要调用Graph API:
创建AAD安全组并添加API服务主体
在Azure AD中创建两个安全组(比如API_Group_A和API_Group_B),分别把Group A、Group B对应的API服务主体加入对应组。配置API X的令牌返回组声明
进入API X的应用注册,找到「令牌配置」→「添加组声明」:- 选择「安全组」,可以选返回组ID或组名称(根据你的需求选)
- 保存配置后,Azure AD会自动把API所属的组信息加入JWT令牌的
groups声明中
在API X中验证组声明
解析JWT的groups声明,检查是否包含API_Group_B的ID或名称,以此判断是否允许访问特殊路由。
对你思路的回应
调用Graph API验证的可行性:这个方案是可行的,但不推荐。你需要给API X的服务主体分配
Directory.Read.All权限,然后每次请求时从JWT里拿到客户端ID(azp或appid声明),调用Graph API的/servicePrincipals/{clientId}/memberOf接口检查所属组。但这样会增加请求延迟和对Graph API的依赖,性能和可靠性都不如前面两种方案。Group B令牌含额外声明的可行性:完全可行!方案一的应用角色就是原生实现这种需求的方式,Group B的API拿到的JWT里会自动包含
roles: ["AccessSpecialStuff"]声明,而Group A的令牌里没有,完美匹配你的理想状态。
总结下来,方案一(应用角色)是最优选择,它更贴合服务对服务的权限控制场景,配置简单,性能优异,也是Azure官方推荐的实现方式。
内容的提问来源于stack exchange,提问作者Alex

