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

Blazor WebAssembly使用OIDC时,静默认证的AuthenticationStateChanged事件不触发

问题:Blazor WASM OIDC静默认证时AuthenticationStateChanged事件不触发

我正在迁移一个此前使用自定义AuthenticationStateProvider的客户端Blazor WebAssembly应用,将其更新为通过Microsoft现成的RemoteAuthenticationService和AddOidcAuthentication()方法对接OIDC身份提供商服务器。

在旧实现中,无论是用户通过登录UI完成登录,还是用户启动应用时已处于登录状态、认证仅需静默验证,AuthenticationStateChanged事件都会触发。这并非我的代码实现的,而是由Microsoft认证框架处理的。

切换至Microsoft的OIDC支持后,AuthenticationStateChanged事件仅在用户通过UI登录时触发,而在静默验证认证(令牌仍有效,用户启动应用)时不会触发。

我希望实现该事件像之前一样触发:每次应用启动,在认证完成后触发事件——无论是通过登录UI路由完成认证,还是因令牌仍有效而通过OIDC服务器静默解析认证等场景。

我的OIDC认证子系统配置如下:

builder.Services.AddOidcAuthentication(options => {

    // Configure our OIDC Identity Provider
    options.ProviderOptions.Authority = "{OIDC-PROVIDER-AUTHORITY-URL}";
    options.ProviderOptions.ClientId = "{OIDC-CLIENT-ID}";
    options.ProviderOptions.ResponseMode = "query";
    options.ProviderOptions.DefaultScopes.Add("email"); // openid and profile are already there by default
});

builder.Services.AddAuthorizationCore(options => {
    options.AddPolicy("IsCustomUser", policy => policy.RequireClaim("custom_user", "true"));
    options.AddPolicy("IsCustomAdmin", policy => policy.RequireClaim("custom_admin", "true"));
});

请问有什么方法能让AuthenticationStateChanged事件在静默认证验证时也触发?


解决方案

方法1:自定义RemoteAuthenticationProvider主动触发状态变更

创建自定义OIDC认证提供者,继承RemoteAuthenticationProvider<RemoteAuthenticationState>,在静默认证和常规登录完成后手动调用NotifyAuthenticationStateChanged触发事件。

public class CustomOidcAuthenticationProvider : RemoteAuthenticationProvider<RemoteAuthenticationState>
{
    private readonly IUserAuthenticationStateProvider _authStateProvider;

    public CustomOidcAuthenticationProvider(IUserAuthenticationStateProvider authStateProvider)
    {
        _authStateProvider = authStateProvider;
    }

    public override async Task<RemoteAuthenticationResult<RemoteAuthenticationState>> ProcessSignInAsync(RemoteAuthenticationContext<RemoteAuthenticationState> context)
    {
        var result = await base.ProcessSignInAsync(context);
        
        if (result.Status == RemoteAuthenticationStatus.Success)
        {
            await TriggerAuthStateChange();
        }
        
        return result;
    }

    public override async Task<RemoteAuthenticationResult<RemoteAuthenticationState>> ProcessSilentSignInAsync(RemoteAuthenticationContext<RemoteAuthenticationState> context)
    {
        var result = await base.ProcessSilentSignInAsync(context);
        
        if (result.Status == RemoteAuthenticationStatus.Success)
        {
            await TriggerAuthStateChange();
        }
        
        return result;
    }

    private async Task TriggerAuthStateChange()
    {
        await _authStateProvider.NotifyAuthenticationStateChanged(
            _authStateProvider.GetAuthenticationStateAsync());
    }
}

在服务配置中替换默认提供者:

builder.Services.AddOidcAuthentication(options => {
    options.ProviderOptions.Authority = "{OIDC-PROVIDER-AUTHORITY-URL}";
    options.ProviderOptions.ClientId = "{OIDC-CLIENT-ID}";
    options.ProviderOptions.ResponseMode = "query";
    options.ProviderOptions.DefaultScopes.Add("email");
})
.AddRemoteAuthenticationProvider<CustomOidcAuthenticationProvider>();

方法2:利用OIDC事件回调触发状态变更

通过配置OIDC的事件回调,在静默认证成功后直接触发事件,无需自定义整个提供者:

builder.Services.AddOidcAuthentication(options => {
    options.ProviderOptions.Authority = "{OIDC-PROVIDER-AUTHORITY-URL}";
    options.ProviderOptions.ClientId = "{OIDC-CLIENT-ID}";
    options.ProviderOptions.ResponseMode = "query";
    options.ProviderOptions.DefaultScopes.Add("email");
});

builder.Services.PostConfigure<RemoteAuthenticationOptions<OidcProviderOptions>>(options =>
{
    options.Events.OnSilentSignInSucceeded = async context =>
    {
        var authStateProvider = context.HttpContext.RequestServices.GetRequiredService<IUserAuthenticationStateProvider>();
        await authStateProvider.NotifyAuthenticationStateChanged(
            authStateProvider.GetAuthenticationStateAsync());
    };
});

方法3:在App组件中主动触发状态检查

在应用根组件App.razor初始化时,主动获取认证状态,若用户已通过静默认证则手动触发事件:

@inject IUserAuthenticationStateProvider AuthStateProvider
@implements IAsyncDisposable

@code {
    private IDisposable? _authSubscription;

    protected override async Task OnInitializedAsync()
    {
        var authState = await AuthStateProvider.GetAuthenticationStateAsync();
        
        if (authState.User.Identity?.IsAuthenticated == true)
        {
            await AuthStateProvider.NotifyAuthenticationStateChanged(
                AuthStateProvider.GetAuthenticationStateAsync());
        }

        _authSubscription = AuthStateProvider.AuthenticationStateChanged += HandleAuthStateChanged;
        await base.OnInitializedAsync();
    }

    private void HandleAuthStateChanged(Task<AuthenticationState> authStateTask)
    {
        // 你的状态变更处理逻辑
    }

    public async ValueTask DisposeAsync()
    {
        _authSubscription?.Dispose();
        await Task.CompletedTask;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 01:47:03