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

Azure AD Claims未纳入IdentityServer4签发令牌的技术问题咨询

解决IdentityServer4未包含Azure AD Claims到签发令牌的问题

这绝对不是默认设计如此——你完全可以把Azure AD里的租户ID、角色等Claims带到IdentityServer4(IS4)签发的令牌里,只是需要额外的配置来完成Claims的映射和传递。下面是一步步的解决方法:

1. 确保从Azure AD获取到目标Claims

首先,在IS4配置Azure AD作为外部身份提供者时,要开启从UserInfo端点拉取Claims的功能,同时请求正确的Scope来获取你需要的信息:

services.AddAuthentication()
    .AddOpenIdConnect("AzureAD", "Azure AD", options =>
    {
        options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
        options.Authority = "https://login.microsoftonline.com/{你的租户ID}/v2.0";
        options.ClientId = "{你的Azure AD应用Client ID}";
        options.ClientSecret = "{你的Azure AD应用Client Secret}";
        options.ResponseType = "code";
        
        // 关键:开启从UserInfo端点获取额外Claims
        options.GetClaimsFromUserInfoEndpoint = true;
        
        // 请求包含所需信息的Scope
        options.Scope.Add("openid");
        options.Scope.Add("profile");
        options.Scope.Add("email");
        options.Scope.Add("roles"); // 如果需要用户角色,必须添加这个Scope
        
        // 映射Azure AD的原生Claims到更友好的名称(可选但推荐)
        options.ClaimActions.MapUniqueJsonKey("tenant_id", "tid"); // 租户ID对应Azure AD的tid Claim
        options.ClaimActions.MapJsonKey(ClaimTypes.Role, "roles"); // 把roles映射成标准的Role Claim
        
        // 在创建登录票据时手动提取并添加需要的Claims
        options.Events.OnCreatingTicket = context =>
        {
            // 提取并添加租户ID
            var tenantId = context.Principal.FindFirstValue("tid");
            if (!string.IsNullOrEmpty(tenantId))
            {
                context.Identity.AddClaim(new Claim("tenant_id", tenantId));
            }
            
            // 处理多角色场景,确保所有Azure AD返回的角色都被添加
            var azureRoles = context.Principal.FindAll("roles");
            foreach (var role in azureRoles)
            {
                context.Identity.AddClaim(new Claim(ClaimTypes.Role, role.Value));
            }
            
            return Task.CompletedTask;
        };
    });

同时要确保你的Azure AD应用注册已经配置了正确的权限:如果需要读取用户角色,要在应用权限里添加Directory.Read.All(针对目录角色)或者确保你已经在应用里定义了应用角色并分配给了用户。

2. 配置IS4将目标Claims包含到签发的令牌中

光获取到Claims还不够,你需要告诉IS4哪些Claims需要包含到发给API或客户端的令牌里。可以通过配置ApiResource或者Client来实现:

针对ApiResource的配置

services.AddIdentityServer()
    .AddInMemoryApiResources(new List<ApiResource>
    {
        new ApiResource("你的API资源名称")
        {
            // 列出需要包含在访问令牌里的Claims
            UserClaims = { "tenant_id", ClaimTypes.Role, "email", "name" }
        }
    })
    // 其他IS4配置(比如客户端、身份资源等)...

针对Client的配置(如果是客户端凭证流或需要ID令牌包含Claims)

如果是需要ID令牌包含这些Claims,要在Client配置里添加AllowedScopes和Claims:

new Client
{
    ClientId = "你的客户端ID",
    // 其他客户端配置...
    AllowedScopes = { "openid", "profile", "你的API资源名称" },
    // 指定要包含在ID令牌里的Claims
    Claims = { new ClientClaim("tenant_id", "tenant_id") }
}

3. 自定义ProfileService(可选但必要时)

如果默认的ProfileService没有正确传递Claims,你可以自定义一个ProfileService来确保所有需要的Claims都被包含到令牌中:

public class CustomProfileService : IProfileService
{
    public async Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        // 获取当前用户的所有Claims
        var userClaims = context.Subject.Claims.ToList();
        
        // 可以在这里过滤或添加额外的Claims
        // 比如确保tenant_id和role都存在
        context.IssuedClaims = userClaims;
    }

    public async Task IsActiveAsync(IsActiveContext context)
    {
        // 简单标记用户为活跃状态,根据你的业务逻辑调整
        context.IsActive = true;
    }
}

然后把这个自定义服务注册到DI容器中:

services.AddTransient<IProfileService, CustomProfileService>();

最后验证

完成配置后,重新启动IS4和你的应用,登录后解析IS4签发的令牌,应该就能看到来自Azure AD的租户ID、角色等Claims了。如果还是看不到,可以检查:

  • Azure AD是否真的返回了这些Claims(可以用调试工具查看回调时的Claims集合)
  • IS4的ApiResource/Client配置是否正确包含了这些Claims名称
  • 自定义ProfileService是否正确返回了Claims

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 07:53:47