.NET 6.0.5自定义UserClaimsPrincipalFactory登录时不生成声明问题
问题分析
当使用AzureAD(OIDC)登录时,ASP.NET Core Identity的UserClaimsPrincipalFactory默认不会被触发——这个工厂是为Identity本地认证流程(如密码登录)设计的,而AzureAD登录由OIDC中间件独立处理,不会走Identity的Claims生成逻辑。
解决方案
你可以通过OIDC中间件的OnTokenValidated事件,手动集成自定义声明逻辑,既可以直接在事件中从数据库获取数据添加声明,也可以复用你已实现的ApplicationUserClaimsFactory。
方法1:直接在OnTokenValidated中添加声明
修改认证配置,在OIDC的配置里添加OnTokenValidated事件处理:
builder.Services.AddAuthentication() .AddMicrosoftIdentityWebApp(options => { builder.Configuration.Bind("AzureAd", options); options.Events.OnTokenValidated = async context => { // 获取当前用户的邮箱标识 var email = context.Principal.FindFirstValue(ClaimTypes.Email); // 从数据库查询对应的ApplicationUser var userManager = context.HttpContext.RequestServices.GetRequiredService<UserManager<ApplicationUser>>(); var user = await userManager.FindByEmailAsync(email); if (user != null) { // 从数据库获取自定义声明数据,示例中直接添加,实际替换为你的业务逻辑 var identity = (ClaimsIdentity)context.Principal.Identity; identity.AddClaim(new Claim("Test", "true")); identity.AddClaim(new Claim("name", user.UserName)); // 可添加更多从数据库读取的声明 } }; });
方法2:复用自定义的ApplicationUserClaimsFactory
如果想复用已实现的ApplicationUserClaimsFactory,同样在OnTokenValidated中调用它:
builder.Services.AddAuthentication() .AddMicrosoftIdentityWebApp(options => { builder.Configuration.Bind("AzureAd", options); options.Events.OnTokenValidated = async context => { var email = context.Principal.FindFirstValue(ClaimTypes.Email); var userManager = context.HttpContext.RequestServices.GetRequiredService<UserManager<ApplicationUser>>(); var user = await userManager.FindByEmailAsync(email); if (user != null) { // 获取自定义ClaimsPrincipalFactory实例 var claimsFactory = context.HttpContext.RequestServices.GetRequiredService<IUserClaimsPrincipalFactory<ApplicationUser>>(); var customPrincipal = await claimsFactory.CreateAsync(user); // 将原Principal的身份替换为自定义生成的身份 context.Principal = customPrincipal; } }; });
注意事项
- 确保AzureAD用户和你的本地
ApplicationUser已通过邮箱或其他标识正确关联,否则无法查询到对应的本地用户。 - 若使用方法2,你之前通过
AddClaimsPrincipalFactory<ApplicationUserClaimsFactory>()注册工厂的方式是正确的,无需额外修改。
内容的提问来源于stack exchange,提问作者KasperKyhl
相关产品推荐
相关产品推荐

