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

Hosted Blazor WASM对接Azure AD B2C时OnTokenValidated事件不触发如何解决

问题原因
  • OnMessageReceived是JWT验证流程的最早阶段,仅完成了请求头中Token的提取,还未执行Token有效性校验,所以Principal必然为null,无法获取用户声明。
  • OnTokenValidated仅在Token校验完全通过后才会触发,未触发的核心原因通常是:配置写在Blazor WASM客户端项目(该配置仅适用于服务端API的JWT校验场景)、请求受保护接口时未携带有效Access Token、Token校验不通过(如受众、签名、有效期错误等)。
可行解决方案

步骤1:确认配置位置

JWT身份验证相关配置必须写在Hosted Blazor的后端API项目中,不要写到Blazor WASM客户端项目里。

步骤2:补充校验失败日志排查问题

在原有配置基础上增加OnAuthenticationFailed事件,确认是否是Token校验失败导致OnTokenValidated未触发:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(
        JwtBearerOptions =>
        {
            JwtBearerOptions.Events ??= new JwtBearerEvents();
            // 新增校验失败日志,排查具体错误原因
            JwtBearerOptions.Events.OnAuthenticationFailed = context =>
            {
                // 可替换为你项目的日志组件输出错误
                Console.WriteLine($"Token校验失败:{context.Exception.Message}");
                return Task.CompletedTask;
            };
            JwtBearerOptions.Events.OnTokenValidated += OnTokenValidatedCallbackFunc;
        },
        configureMicrosoftIdentityOptions =>
        {
            Configuration.Bind("AzureAdB2C", configureMicrosoftIdentityOptions);
        });

步骤3:触发OnTokenValidated的正确方式

该事件仅会在请求携带有效Token访问加了[Authorize]属性的受保护接口时触发,你可以在前端登录成功后主动调用后端初始化接口触发该流程:

后端新增初始化接口

[ApiController]
[Route("api/[controller]")]
[Authorize]
public class AuthInitController : ControllerBase
{
    private readonly AppDbContext _dbContext;

    public AuthInitController(AppDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    [HttpGet("status")]
    public async Task<IActionResult> GetInitStatus()
    {
        var userId = User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value;
        var user = await _dbContext.Users.FirstOrDefaultAsync(u => u.AdB2cId == userId);
        // 也可以在这里直接写新用户创建逻辑,比在OnTokenValidated中处理更灵活
        if (user == null)
        {
            user = new AppUser
            {
                AdB2cId = userId,
                Email = User.FindFirst(System.Security.Claims.ClaimTypes.Email)?.Value,
                DisplayName = User.FindFirst("name")?.Value,
                IsProfileCompleted = false
            };
            _dbContext.Users.Add(user);
            await _dbContext.SaveChangesAsync();
        }
        return Ok(new { NeedProfileSetup = !user.IsProfileCompleted });
    }
}

前端登录后调用接口判断跳转

在Blazor WASM的登录后页面(如MainLayout、Authentication回调页)添加如下逻辑:

@inject IAccessTokenProvider TokenProvider
@inject HttpClient HttpClient
@inject NavigationManager NavManager

protected override async Task OnInitializedAsync()
{
    var tokenResult = await TokenProvider.RequestAccessToken();
    if (tokenResult.TryGetToken(out var token))
    {
        HttpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token.Value);
        var initStatus = await HttpClient.GetFromJsonAsync<InitStatusDto>("api/AuthInit/status");
        // 新用户未完成配置直接跳转到配置页
        if (initStatus.NeedProfileSetup)
        {
            NavManager.NavigateTo("/profile-setup");
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 20:45:03