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

无法从Identity Server 4获取用户邮箱Claim问题求助

Identity Server 4 + Swagger授权问题:邮箱Claim无法映射到用户Claims集合

Identity Server端配置

public static IEnumerable<ApiScope> ApiScopes =>
    new List<ApiScope>()
    {
        new ApiScope("PetAPI", "Pets WebAPI"),
        new ApiScope("NotificationsAPI", "Notifications WebAPI"),
        new ApiScope("ScheduleAPI","Schedule WebAPI")
    };

public static IEnumerable<IdentityResource> IdentityResources =>
    new List<IdentityResource>()
    {
        new IdentityResources.OpenId(),
        new IdentityResources.Email(),
        new IdentityResources.Profile()
    };

public static IEnumerable<ApiResource> ApiResources =>
    new List<ApiResource>()
    {
        new ApiResource("PetAPI"),
        new ApiResource("NotificationsAPI"),
        new ApiResource("ScheduleAPI")
    };

public static IEnumerable<Client> Clients =>
    new List<Client>()
    {
        new Client()
        {
           ClientId = "pmcs-client-id",
           ClientSecrets = { new Secret("client_secret".ToSha256()) },
           ClientName = "M2M Client",
           AllowedGrantTypes = GrantTypes.ClientCredentials,
           AllowedScopes = {
               IdentityServerConstants.StandardScopes.OpenId,
               IdentityServerConstants.StandardScopes.Profile,
               IdentityServerConstants.StandardScopes.Email,
               "PetAPI",
               "NotificationsAPI",
               "ScheduleAPI"
           }
        },
        new Client()
        {
            ClientId = "swagger-client-id",
            ClientSecrets = { new Secret("client_secret".ToSha256()) },
            ClientName = "Swagger Client",
            AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
            AllowedScopes = {
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Email,
                IdentityServerConstants.StandardScopes.Profile,
                "PetAPI",
                "NotificationsAPI",
                "ScheduleAPI"
            }
        }
    };

微服务端配置

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
            {
                options.Authority = AuthConfiguration.Authority;
                options.RequireHttpsMetadata = AuthConfiguration.RequireHttpsMetadata;
                options.Audience = AuthConfiguration.Audience;
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateAudience = AuthConfiguration.ValidateAudience,
                };
            })
                .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, config =>
            {
                config.Authority = AuthConfiguration.Authority;
                config.ClientId = AuthConfiguration.SwaggerClientId;
                config.ClientSecret = AuthConfiguration.ClientSecret;
                config.SaveTokens = true;
                config.ResponseType = "id_token";
                config.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateAudience = AuthConfiguration.ValidateAudience
                };

                config.Scope.Add(AuthConfiguration.ScheduleScope);
                config.Scope.Add("email");
                config.Scope.Add("openid");
                config.Scope.Add("profile");

                config.GetClaimsFromUserInfoEndpoint = true;
                config.ClaimActions.MapAll();
            });

获取Claim的代码

var emailFromClaims = _context.HttpContext?.User?.FindFirst(ClaimTypes.Email)?.Value;

问题现象

Id Token中存在邮箱Claim,但调用上述代码无法从HttpContext.User.Claims集合中获取到邮箱值。


解决步骤

  1. 调整OpenID Connect的ResponseType
    当前ResponseType = "id_token"仅返回身份令牌,针对ResourceOwnerPassword授权类型,建议改为"id_token token"以同时获取身份令牌和访问令牌,确保用户信息能被正确解析:

    config.ResponseType = "id_token token";
    
  2. 显式映射邮箱Claim
    尽管使用了ClaimActions.MapAll(),但Identity Server返回的邮箱Claim键为email,而ClaimTypes.Email对应的是完整URI格式(http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress),需显式添加映射:

    config.ClaimActions.MapJsonKey(ClaimTypes.Email, "email");
    
  3. 完善TokenValidationParameters配置
    在OpenID Connect配置中,指定Claim类型的映射规则,确保框架能正确识别标准Claim类型:

    config.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateAudience = AuthConfiguration.ValidateAudience,
        NameClaimType = ClaimTypes.Name,
        RoleClaimType = ClaimTypes.Role
    };
    
  4. 确认认证方案匹配
    微服务端默认认证方案为JwtBearer,但Swagger使用的是OpenIdConnect方案。需确保受保护的API控制器使用正确的认证方案,可通过特性指定:

    [Authorize(AuthenticationSchemes = OpenIdConnectDefaults.AuthenticationScheme)]
    

    或者调整默认认证方案为OpenIdConnect:

    services.AddAuthentication(options =>
    {
        options.DefaultScheme = OpenIdConnectDefaults.AuthenticationScheme;
    })
    // ...后续的AddJwtBearer和AddOpenIdConnect配置
    
  5. 验证UserInfo端点返回
    确认Identity Server的UserInfo端点能正确返回emailClaim,可通过调试或直接访问端点验证返回内容是否包含邮箱字段。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 03:15:42