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

.NET Core OpenID Connect配置中Profile声明重命名映射问题咨询

问题原因

你之前的MapJsonKey配置不生效有两个核心原因:

  1. 你注释掉了options.GetClaimsFromUserInfoEndpoint = true,ClaimActions下的映射规则默认仅作用于从UserInfo端点拉取的声明数据,不会处理ID Token/Access Token中自带的声明。
  2. 你的第三行映射代码参数填写错误:MapJsonKey的入参顺序是(目标声明名, 原始JSON键名),你需要把mail映射为Mail,对应的配置应该是MapJsonKey("Mail", "mail"),你写的原始键为大写Mail,匹配不到返回的小写mail字段。

另外框架默认开启了JWT内置声明映射,会自动把mail、givenName这类标准声明转换为System.Security.Claims.ClaimTypes下的URI格式声明名,也会干扰自定义映射的匹配。


解决方案

有两种可落地的实现方式,你可以根据自己的场景选择:

方式1:走UserInfo端点映射(无需写业务钩子)

如果你的身份提供商支持UserInfo端点,调整配置即可直接让MapJsonKey规则生效:

// 先在配置最前面清空默认JWT声明映射,避免框架自动转换声明名
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

services.AddAuthentication(options => {
    options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, o =>
{
    o.Cookie.Name = "GCOWebCookie";
    o.AccessDeniedPath = "/AccessDenied";
})
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options => {
    options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.Authority = config["OneId:Authority"];
    options.ClientId = config["OneId:ClientId"];
    options.ResponseType = "code";
    options.ClientSecret = config["OneId:ClientSecret"];
    options.SaveTokens = true;
    // 开启从UserInfo端点拉取声明
    options.GetClaimsFromUserInfoEndpoint = true;
    options.UsePkce = true;

    // 修正后的声明映射规则
    options.ClaimActions.MapJsonKey("EmployeeType", "employeeType");
    options.ClaimActions.MapJsonKey("FirstName", "givenName");
    options.ClaimActions.MapJsonKey("Mail", "mail");
});

方式2:用OnTokenValidated钩子处理(最可控,无需依赖UserInfo端点)

如果你不想调用UserInfo端点,直接用Token自带的声明,用这个方案可以完全避开框架内置映射的干扰,自定义程度最高:
在AddOpenIdConnect的配置块中添加事件回调即可:

options.Events.OnTokenValidated = context =>
{
    if (context.Principal?.Identity is ClaimsIdentity identity)
    {
        // 读取原始声明值
        var employeeType = identity.FindFirst("employeeType")?.Value;
        var mail = identity.FindFirst("mail")?.Value;
        var givenName = identity.FindFirst("givenName")?.Value;

        // 可选:删除原有名称的声明
        if (employeeType != null) identity.RemoveClaim(identity.FindFirst("employeeType"));
        if (mail != null) identity.RemoveClaim(identity.FindFirst("mail"));
        if (givenName != null) identity.RemoveClaim(identity.FindFirst("givenName"));

        // 添加自定义名称的声明
        if (employeeType != null) identity.AddClaim(new Claim("EmployeeType", employeeType));
        if (mail != null) identity.AddClaim(new Claim("Mail", mail));
        if (givenName != null) identity.AddClaim(new Claim("FirstName", givenName));
    }
    return Task.CompletedTask;
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 06:15:03