Azure AD客户端凭证流调用下游API的客户端标识与数据权限问题
解决方案:Azure API客户端凭据流的身份识别与数据访问限制
核心思路
你的场景核心是在无用户上下文的客户端凭据流中,稳定识别调用方客户端(对应公司),并在跨API调用时保留该身份信息,实现数据隔离。以下是几种可行的落地方案:
方案1:提取客户端标识并通过请求头传递给下游API
- 在前端API中,从客户端凭据令牌中提取可靠的客户端标识:
azp:调用方客户端的应用ID(固定不变,可直接关联到对应公司)oid:调用方客户端的Azure AD对象ID(同样稳定)
- 调用下游API时,将该标识放入自定义HTTP请求头(比如
X-Original-Client-ID) - 下游API先验证上游API的身份(通过令牌确认调用来自可信的前端API),再读取请求头中的客户端ID,以此限制数据访问范围
方案2:用应用角色(App Roles)映射客户端权限
- 在前端API的Azure AD应用注册中,为每个第三方客户端创建专属的应用角色(例如
CompanyA_Access、CompanyB_Access) - 将对应角色分配给各个第三方客户端应用
- 客户端通过凭据流获取的令牌中会包含
roles声明,前端API和下游API都可以直接通过该声明识别客户端所属公司,实现数据隔离- 优势:角色声明是Azure AD原生支持的,令牌验证时自动生效,无需额外处理
方案3:自定义下游API的令牌获取逻辑,嵌入原始客户端标识
- 在前端API调用下游API时,手动构建令牌请求,将原始客户端标识作为自定义参数传入:
var client = new HttpClient(); var requestBody = new Dictionary<string, string> { ["grant_type"] = "client_credentials", ["client_id"] = "<你的前端API客户端ID>", ["client_secret"] = "<你的前端API客户端密钥>", ["scope"] = "<下游API的访问范围>", ["original_client_id"] = "<从原始令牌中提取的azp值>" }; var response = await client.PostAsync("https://login.microsoftonline.com/<租户ID>/oauth2/v2.0/token", new FormUrlEncodedContent(requestBody)); - 下游API的应用注册需配置允许接收
original_client_id作为可选声明,或在令牌验证逻辑中从令牌扩展信息读取该字段,以此识别原始调用方
关键注意事项
- 禁止使用ROPC流:微软明确不推荐该方案,存在密码泄露、身份伪造等安全风险
- 确保跨API身份可信:下游API必须验证上游API的令牌合法性,避免恶意请求伪造客户端标识
- 优先使用原生声明:
azp、roles等Azure AD原生声明比自定义声明更可靠,无需额外配置即可在令牌中获取
内容的提问来源于stack exchange,提问作者Erik Särner
相关产品推荐
相关产品推荐

