无法从Identity Server 4获取用户邮箱Claim问题求助
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集合中获取到邮箱值。
解决步骤
调整OpenID Connect的ResponseType
当前ResponseType = "id_token"仅返回身份令牌,针对ResourceOwnerPassword授权类型,建议改为"id_token token"以同时获取身份令牌和访问令牌,确保用户信息能被正确解析:config.ResponseType = "id_token token";显式映射邮箱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");完善TokenValidationParameters配置
在OpenID Connect配置中,指定Claim类型的映射规则,确保框架能正确识别标准Claim类型:config.TokenValidationParameters = new TokenValidationParameters { ValidateAudience = AuthConfiguration.ValidateAudience, NameClaimType = ClaimTypes.Name, RoleClaimType = ClaimTypes.Role };确认认证方案匹配
微服务端默认认证方案为JwtBearer,但Swagger使用的是OpenIdConnect方案。需确保受保护的API控制器使用正确的认证方案,可通过特性指定:[Authorize(AuthenticationSchemes = OpenIdConnectDefaults.AuthenticationScheme)]或者调整默认认证方案为OpenIdConnect:
services.AddAuthentication(options => { options.DefaultScheme = OpenIdConnectDefaults.AuthenticationScheme; }) // ...后续的AddJwtBearer和AddOpenIdConnect配置验证UserInfo端点返回
确认Identity Server的UserInfo端点能正确返回emailClaim,可通过调试或直接访问端点验证返回内容是否包含邮箱字段。
内容的提问来源于stack exchange,提问作者moltenessence

