.NET Core OpenID Connect配置中Profile声明重命名映射问题咨询
问题原因
你之前的MapJsonKey配置不生效有两个核心原因:
- 你注释掉了
options.GetClaimsFromUserInfoEndpoint = true,ClaimActions下的映射规则默认仅作用于从UserInfo端点拉取的声明数据,不会处理ID Token/Access Token中自带的声明。 - 你的第三行映射代码参数填写错误:
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
相关产品推荐
相关产品推荐

