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

.NET5 Razor应用对接Azure AD B2C后,更新用户信息如何同步令牌刷新User.Identity.Name

解决Azure AD B2C .NET5 Razor应用用户姓名更新后User.Identity.Name不同步的问题

这个问题我之前在对接Azure AD B2C的.NET应用时也遇到过——核心原因是用户信息更新后,当前会话里的ID Token还是旧的,所以User.Identity.Name不会自动同步。咱们不用绕ResetPassword这种不合适的流程,用下面两种方案就能解决:

方案一:服务器端静默刷新令牌(无用户感知)

这种方案是在用户更新姓名后,后端直接用Refresh Token获取新的ID Token,更新当前用户的Claims,全程不需要用户操作。

前提准备

  1. 确保你的Azure AD B2C应用注册已经添加了offline_access权限(需要在Azure门户的应用注册->API权限里添加,然后授予管理员同意)。
  2. 在你的.NET5项目配置中,开启令牌保存:
    // 在Startup.cs或Program.cs的服务配置中
    services.AddMicrosoftIdentityWebAppAuthentication(Configuration, "AzureAdB2C")
        .EnableTokenAcquisitionToCallDownstreamApi(new[] { "openid", "profile", "offline_access" })
        .AddInMemoryTokenCaches();
    
    // 或者手动配置OpenIdConnect选项
    services.Configure<OpenIdConnectOptions>(OpenIdConnectDefaults.AuthenticationScheme, options =>
    {
        options.SaveTokens = true; // 必须开启,这样Refresh Token才会被保存
    });
    

实现步骤

在处理用户姓名更新的POST方法中,完成Graph API更新用户信息后,触发令牌刷新:

using Microsoft.AspNetCore.Identity;
using Microsoft.Identity.Web;
using System.Threading.Tasks;

public class ProfileModel : PageModel
{
    private readonly ITokenAcquisition _tokenAcquisition;
    private readonly SignInManager<IdentityUser> _signInManager;

    public ProfileModel(ITokenAcquisition tokenAcquisition, SignInManager<IdentityUser> signInManager)
    {
        _tokenAcquisition = tokenAcquisition;
        _signInManager = signInManager;
    }

    public async Task<IActionResult> OnPostUpdateNameAsync(string newFullName)
    {
        // 1. 调用Azure AD B2C Graph API更新用户的displayName(这一步你应该已经实现了)
        await UpdateUserDisplayNameInB2C(newFullName);

        // 2. 尝试静默刷新令牌,获取最新的用户Claims
        try
        {
            // 请求openid和profile范围,确保获取包含姓名的ID Token
            await _tokenAcquisition.GetAccessTokenForUserAsync(new[] { "openid", "profile" });
            
            // 更新当前用户的ClaimsPrincipal,让User.Identity.Name立即生效
            var refreshedPrincipal = await _signInManager.RefreshSignInAsync(User);
            HttpContext.User = refreshedPrincipal;
        }
        catch (MsalUiRequiredException)
        {
            // 如果Refresh Token过期或无效,静默刷新失败,引导用户重新登录
            return Challenge(OpenIdConnectDefaults.AuthenticationScheme, new AuthenticationProperties
            {
                RedirectUri = Url.Page("/Profile")
            });
        }

        // 3. 重定向回个人主页,此时导航栏已经显示新姓名
        return RedirectToPage("/Profile");
    }

    // 你已实现的更新用户姓名的Graph API调用方法
    private async Task UpdateUserDisplayNameInB2C(string newFullName)
    {
        // 这里写调用Graph API更新用户displayName的逻辑
    }
}

方案二:引导用户静默重认证(无感知刷新令牌)

如果服务器端刷新遇到限制,也可以在更新成功后,引导用户进行一次静默的B2C认证——用户不会看到登录/编辑页面,直接返回应用并获取新令牌。

实现代码

在更新姓名成功后,返回Challenge并添加prompt=none参数:

public async Task<IActionResult> OnPostUpdateNameAsync(string newFullName)
{
    // 1. 调用Graph API更新用户姓名
    await UpdateUserDisplayNameInB2C(newFullName);

    // 2. 触发静默认证,获取新令牌
    return Challenge(new AuthenticationProperties
    {
        RedirectUri = Url.Page("/Profile"),
        Items = { { "prompt", "none" } } // 静默模式,无用户交互
    }, OpenIdConnectDefaults.AuthenticationScheme);
}

注意事项

  • 如果用户的B2C会话已经过期,prompt=none会触发错误,这时候你需要在OnAuthenticationFailed事件中捕获异常,引导用户正常登录。
  • 这种方式依赖B2C的会话有效性,如果用户很久没操作,还是需要手动登录一次。

关键验证点

  • 确保你在Graph API中更新的是用户的displayName属性——因为默认情况下User.Identity.Name映射的是ID Token中的name声明,而这个声明通常来自B2C用户的displayName。
  • 如果你的应用自定义了Claim映射,需要确认User.Identity.Name对应的Claim是否正确更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 12:02:40