You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在APIM策略中验证非Graph AAD令牌用户是否属于邮件分发列表

问题翻译

我在Azure API Management(APIM)中有一个API,该API操作使用后端应用注册的自定义范围(并非User.Read)验证Azure Active Directory(AAD)生成的JWT(客户端ID对应该后端范围的授权应用注册)。JWT验证通过后,我能否提取用户信息并验证该用户是否属于某个邮件分发列表(DL)?如果可以,如何在APIM策略中实现?

我了解MS Graph API,已经通过Postman确认该DL在租户组中并获取了其组ID,也确认用户是该组成员。但Graph API需要的令牌和客户端提供的令牌不同(范围来自不同域:自定义应用注册 vs Graph),这让我卡壳了。是否需要让客户端应用额外获取Graph令牌并在单独标头中传递,还是可以在APIM内部协调实现?


解决方案

不需要让客户端额外传递Graph令牌,完全可以在APIM内部通过托管身份调用MS Graph API完成用户组验证,步骤如下:

1. 为APIM启用系统分配托管身份

  • 在Azure门户打开你的APIM实例,进入「身份」选项卡,启用「系统分配」托管身份,保存后记录生成的对象ID(后续授权用)。

2. 为托管身份授予Graph API权限

  • 进入Azure AD的「应用注册」,搜索并打开「Microsoft Graph」应用。
  • 进入「API权限」,点击「添加权限」,选择「应用权限」,找到GroupMember.Read.All权限(DL在AAD中以组形式存在,该权限允许查询组成员身份),添加后点击「授予管理员同意」。

3. 在APIM策略中实现完整流程

步骤分解

  1. 验证客户端JWT:先执行JWT验证,确保令牌合法且包含自定义范围。
  2. 提取用户ID:从验证后的JWT中提取oid(用户对象ID)声明。
  3. 获取Graph访问令牌:用APIM的authentication-managed-identity策略获取MS Graph的访问令牌。
  4. 调用Graph API检查成员身份:发送GET请求到Graph的组成员校验接口,204响应代表用户是成员,404则不是。
  5. 控制API访问:若用户不在目标DL中,返回403禁止访问;否则继续转发请求到后端。

完整策略示例

<policies>
    <inbound>
        <!-- 1. 验证客户端JWT -->
        <validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Invalid token">
            <openid-config url="https://login.microsoftonline.com/{你的租户ID}/v2.0/.well-known/openid-configuration" />
            <required-claims>
                <claim name="aud" match="any">
                    <value>{你的后端应用注册客户端ID}</value>
                </claim>
                <claim name="scp" match="any">
                    <value>{你的自定义范围}</value>
                </claim>
            </required-claims>
        </validate-jwt>

        <!-- 2. 提取用户OID -->
        <set-variable name="userOid" value="@(context.Request.Headers.GetValueOrDefault("Authorization").Split(' ')[1].AsJwt()?.Claims.FirstOrDefault(c => c.Type == "oid")?.Value)" />

        <!-- 3. 获取Graph API令牌 -->
        <authentication-managed-identity resource="https://graph.microsoft.com" output-token-variable-name="graphToken" ignore-error="false" />

        <!-- 4. 调用Graph API检查成员身份 -->
        <send-request mode="new" response-variable-name="graphResponse" timeout="20" ignore-error="true">
            <set-url>@($"https://graph.microsoft.com/v1.0/groups/{你的DL组ID}/members/{((string)context.Variables["userOid"])}/$ref")</set-url>
            <set-method>GET</set-method>
            <set-header name="Authorization" exists-action="override">
                <value>@($"Bearer {((string)context.Variables["graphToken"])})"</value>
            </set-header>
        </send-request>

        <!-- 5. 根据结果控制访问 -->
        <choose>
            <when condition="@(((IResponse)context.Variables["graphResponse"]).StatusCode != 204)">
                <return-response>
                    <set-status code="403" reason="Forbidden" />
                    <set-body>@{
                        return "用户不属于指定的邮件分发列表,无权访问。";
                    }</set-body>
                </return-response>
            </when>
        </choose>

        <!-- 转发请求到后端 -->
        <base />
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

关键说明

  • 托管身份优势:APIM系统分配托管身份可安全获取Graph令牌,无需客户端参与,避免多令牌管理复杂度,降低泄露风险。
  • 权限选择:GroupMember.Read.All是应用权限,适合APIM后台调用Graph,无需用户交互;若用委托权限则需用户同意,不符合后台验证场景。
  • 错误处理:ignore-error="true"用于捕获Graph的404响应,再通过choose判断是否拒绝访问;其他错误可在on-error块中处理。

不推荐的替代方案

若要求客户端传递Graph令牌,需客户端同时获取两个令牌(一个用于API验证,一个用于Graph),会增加客户端开发复杂度,且令牌管理风险更高,不建议采用。

内容的提问来源于stack exchange,提问作者camios

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 15:25:36