Blazor WASM:User.Identity?.IsAuthenticated为true但无法静默获取访问令牌
解决Blazor WASM Azure AD B2C 认证状态误判问题
1. 替代User.Identity?.IsAuthenticated的判断方式
不要仅依赖ClaimsIdentity的IsAuthenticated属性——只要AuthenticationType非空它就会返回true,哪怕令牌已过期。推荐两种更精准的判断方式:
直接验证令牌有效期
从用户Claims中提取exp声明,转换为时间后对比当前UTC时间:private bool IsUserWithValidToken() { if (User.Identity?.IsAuthenticated != true) return false; var expClaim = User.Claims.FirstOrDefault(c => c.Type == "exp"); if (expClaim == null || !long.TryParse(expClaim.Value, out var expTimestamp)) return false; var expirationTime = DateTimeOffset.FromUnixTimeSeconds(expTimestamp).UtcDateTime; return expirationTime > DateTime.UtcNow; }通过MSAL静默验证令牌可用性
注入IPublicClientApplication,尝试静默获取令牌(不触发跳转),以此判断用户状态:private async Task<bool> CanGetValidTokenSilently() { var accounts = await _publicClientApplication.GetAccountsAsync(); var currentAccount = accounts.FirstOrDefault(); if (currentAccount == null) return false; try { var result = await _publicClientApplication.AcquireTokenSilent(new[] { "你的API作用域" }, currentAccount) .ExecuteAsync(); return !string.IsNullOrEmpty(result.AccessToken); } catch (MsalUiRequiredException) { // 需要用户交互才能获取令牌,说明当前令牌无效/已过期 return false; } }这种方式直接验证后续API调用能否拿到有效令牌,从根源避免异常跳转。
2. 是否需要自定义策略?
如果你的场景需要结合角色、特定声明、令牌有效期等多维度认证规则,自定义授权策略是合适的选择:
注册自定义策略
在Program.cs中添加策略及验证逻辑:builder.Services.AddAuthorization(options => { options.AddPolicy("ValidAuthenticatedUser", policy => { policy.RequireAuthenticatedUser(); policy.AddRequirements(new ValidTokenRequirement()); }); }); public class ValidTokenRequirement : IAuthorizationRequirement { } public class ValidTokenHandler : AuthorizationHandler<ValidTokenRequirement> { protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ValidTokenRequirement requirement) { var expClaim = context.User.Claims.FirstOrDefault(c => c.Type == "exp"); if (expClaim != null && long.TryParse(expClaim.Value, out var expTimestamp)) { var expirationTime = DateTimeOffset.FromUnixTimeSeconds(expTimestamp).UtcDateTime; if (expirationTime > DateTime.UtcNow) { context.Succeed(requirement); } } return Task.CompletedTask; } }在组件中使用策略
通过IAuthorizationService验证策略:@inject IAuthorizationService AuthorizationService @code { private bool IsValidUser { get; set; } protected override async Task OnInitializedAsync() { IsValidUser = (await AuthorizationService.AuthorizeAsync(User, "ValidAuthenticatedUser")).Succeeded; } }
3. 额外优化建议
捕获异常后自定义处理
若仍有场景触发AccessTokenNotAvailableException,不要直接调用Redirect(),改为提示用户主动登录:try { // API调用逻辑 } catch (AccessTokenNotAvailableException ex) { ShowLoginPrompt = true; // 用户点击登录按钮后,再调用ex.Redirect() }调整MSAL缓存策略
配置MSAL时优化令牌缓存,及时清理无效凭证:builder.Services.AddMsalAuthentication(options => { // 其他配置... options.ProviderOptions.Cache.CacheLocation = CacheLocation.LocalStorage; options.ProviderOptions.Cache.StoreAuthStateInCookie = false; });
内容的提问来源于stack exchange,提问作者Paul Suart
相关产品推荐
相关产品推荐

