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

Azure托管标识已分配角色但令牌中无该角色的问题排查

问题解答

理解误区与差异原因

你遇到的核心问题是托管标识(应用身份)与用户身份在Azure AD令牌生成逻辑上的本质区别:

  • 用户身份通过OAuth 2.0授权流(如授权码、隐式流)获取令牌时,roles声明来自用户/用户组被分配的「可分配给用户的应用角色」,这类角色会直接嵌入令牌,用于标识用户权限。
  • 托管标识属于服务主体(应用身份),它通过客户端凭证流获取令牌,此时令牌是否包含roles声明有两个关键前提:
    1. 分配给托管标识的必须是「仅应用类型」的应用角色(创建时需选择「允许分配给:应用程序」);
    2. 目标API的Azure AD应用注册中必须明确定义这些「仅应用角色」,且角色分配已正确关联到托管标识对应的服务主体。

你当前的令牌无角色声明,大概率是因为角色类型不匹配,或者目标API的应用注册未正确配置仅应用角色,导致Azure AD在颁发客户端凭证流令牌时未注入角色信息。

实现相同功能的步骤

1. 确认角色配置与分配正确性

  • 登录Azure门户,找到目标API的应用注册,进入「应用角色」页面,确保已创建仅应用类型的角色。
  • 进入Azure AD的「企业应用」,找到你的托管标识对应的服务主体,进入「角色和权限」页面,确认已分配上述仅应用角色。

2. 修正APIM策略参数

检查authentication-managed-identity中的resource参数:

  • 必须填写目标API的应用ID URI(如api://your-api-client-id)或目标API的客户端ID,确保与目标API应用注册中的信息完全一致。
  • 你当前策略中resource值存在拼写错误({{the-api-I-want-toca--}}),需修正为正确的资源标识。

修正后的策略示例:

<inbound>
    <authentication-managed-identity resource="api://your-target-api-client-id" client-id="{{apim-clientId}}" output-token-variable-name="access-token" ignore-error="false" />
    <return-response>
        <set-status code="200" reason="OK" />
        <set-body>@("Bearer " + (string)context.Variables["access-token"])</set-body>
    </return-response>
</inbound>

3. 验证令牌内容

调用APIM操作获取令牌后,用JWT解析工具(如本地JWT解析库)解析,确认:

  • aud(受众)字段与目标API的应用ID URI/客户端ID一致;
  • iss(颁发者)为Azure AD的正确端点(如https://login.microsoftonline.com/your-tenant-id/v2.0);
  • 若角色分配正确,roles声明会出现在令牌的payload中。

4. 备选方案(若Azure AD未返回角色)

如果因特殊原因Azure AD未注入角色声明,可在APIM策略中手动添加角色(仅推荐临时场景,需确保权限逻辑安全):

<inbound>
    <authentication-managed-identity resource="api://your-target-api-client-id" client-id="{{apim-clientId}}" output-token-variable-name="access-token" ignore-error="false" />
    <!-- 手动添加角色声明到令牌 -->
    <set-header name="Authorization" exists-action="override">
        <value>@{
            var token = (string)context.Variables["access-token"];
            var jwt = new JwtSecurityToken(token);
            var newClaims = jwt.Claims.Append(new Claim("roles", "Developer"));
            var newJwt = new JwtSecurityToken(jwt.Issuer, jwt.Audiences.First(), newClaims, jwt.ValidFrom, jwt.ValidTo, jwt.SigningCredentials);
            return "Bearer " + new JwtSecurityTokenHandler().WriteToken(newJwt);
        }</value>
    </set-header>
    <return-response>
        <set-status code="200" reason="OK" />
        <set-body>@(context.Request.Headers.GetValueOrDefault("Authorization"))</set-body>
    </return-response>
</inbound>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 18:53:17