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

Blazor WASM独立应用调用Graph API 24小时后提示Access token为空

问题诊断与解决方案:Blazor WASM 24小时后Graph API令牌失效及登录跳转异常

核心问题分析

  • 应用运行24小时后令牌过期,GraphAuthenticationProvider获取令牌时返回RequiresRedirect状态,但Blazor默认认证机制未自动触发跳转——自定义账户工厂可能覆盖了部分默认的令牌刷新逻辑,导致状态同步异常
  • 手动处理RequiresRedirect时未正确控制跳转触发时机,引发多次登录循环;登录完成后未同步Blazor认证状态,导致卡在“Completing login...”页面

解决方案步骤

1. 修复GraphAuthenticationProvider的令牌处理逻辑

在AuthenticateRequestAsync中,精准处理RequiresRedirect状态,避免重复跳转:

public async Task AuthenticateRequestAsync(HttpRequestMessage request)
{
    var result = await _tokenProvider.GetAccessTokenAsync(new TokenRequestContext(scopes));
    
    if (result.Status == TokenResultStatus.RequiresRedirect)
    {
        // 仅当前页面未在登录流程中时触发跳转
        if (!_navigationManager.Uri.Contains("authentication/login"))
        {
            var returnUrl = Uri.EscapeDataString(_navigationManager.Uri);
            _navigationManager.NavigateTo($"authentication/login?returnUrl={returnUrl}");
            return;
        }
    }
    else if (result.Status == TokenResultStatus.Success)
    {
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.Value);
    }
    else
    {
        throw new UnauthorizedAccessException("无法获取有效访问令牌");
    }
}

2. 同步自定义账户工厂的令牌状态

在CustomAccountFactory的CreateUserAsync中,确保令牌相关附加属性被正确保留到ClaimsPrincipal,避免本地存储令牌丢失:

public override async ValueTask<ClaimsPrincipal> CreateUserAsync(RemoteUserAccount account, RemoteAuthenticationUserOptions options)
{
    var user = await base.CreateUserAsync(account, options);
    
    if (user.Identity is ClaimsIdentity identity)
    {
        // 保留令牌相关的附加属性
        var tokenProps = account.AdditionalProperties
            .Where(kv => kv.Key.Contains("access_token") || kv.Key.Contains("refresh_token"));
        
        foreach (var prop in tokenProps)
        {
            identity.AddClaim(new Claim(prop.Key, prop.Value.ToString()));
        }
    }
    
    return user;
}

3. 优化Program.cs中的认证配置

确保启用本地存储缓存、正确配置跳转路径,并绑定自定义账户工厂:

builder.Services.AddMsalAuthentication(options =>
{
    builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
    options.ProviderOptions.DefaultAccessTokenScopes.Add("https://graph.microsoft.com/User.Read");
    
    // 配置本地存储维护令牌
    options.ProviderOptions.Cache.CacheLocation = "localStorage";
    // 明确认证跳转路径
    options.AuthenticationPaths.LogInPath = "/authentication/login";
    options.AuthenticationPaths.LogInCallbackPath = "/authentication/login-callback";
    options.AuthenticationPaths.LogOutPath = "/authentication/logout";
    options.AuthenticationPaths.LogOutCallbackPath = "/authentication/logout-callback";
    
    // 注入自定义账户工厂
    options.UserOptions.AccountFactory = sp => sp.GetRequiredService<CustomAccountFactory>();
});

4. 修复登录完成后的状态同步

在Authentication.razor组件中,登录回调后强制刷新认证状态并跳转首页:

@page "/authentication/{action}"
@inject AuthenticationStateProvider AuthStateProvider
@inject NavigationManager NavManager

@code {
    [Parameter] public string Action { get; set; }

    protected override async Task OnParametersSetAsync()
    {
        if (Action.Equals("login-callback", StringComparison.OrdinalIgnoreCase))
        {
            // 强制刷新认证状态,同步本地令牌信息
            await ((MsalAuthenticationStateProvider)AuthStateProvider).GetAuthenticationStateAsync();
            // 跳转到首页或原返回页
            var returnUrl = NavManager.QueryString("returnUrl") ?? "/";
            NavManager.NavigateTo(returnUrl, forceLoad: true);
        }
    }
}

关键注意事项

  • 跳转登录时必须携带returnUrl,否则登录后无法回到用户原来的操作页面
  • 自定义账户工厂不能过滤令牌相关的附加属性,否则本地存储的令牌会丢失,导致后续认证失败
  • 确保AuthenticationService.js在index.html中被正确引用,这是Blazor WASM认证的核心前端依赖

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 02:52:33