Search code examples
asp.net-coreauthenticationblazor.net-9.0

AuthenticationStateSerialization does not reflect server changes back to the client


I have a Blazor web app with per-component render mode, some (including the router/layout) use Static SSR, and some pages/components are set to use WASM with pre-rendering disabled. I also disabled the InteractiveServer mode and do not plan to use it.

My goal is to have an AuthenticationState available both when rendering static SSR and WASM components with the possibility to read the same user claims on both places.

Based on the article here, the best-practice is to have the user authenticate on the server, and have it flow the states to WASM. In .NET 9, Microsoft has added a new built-in feature doing just that. It is detailed in the article. It states:

  • In the ASP.NET server project, call: AddAuthenticationStateSerialization(options => options.SerializeAllClaims = true)

  • In the WASM client project, call: AddAuthenticationStateDeserialization()

This automatically register an AuthenticationStateProvider in both projects and is supposed to handle flowing auth values from server to client.

My problem is that this only seems to work is the user is authenticated BEFORE the web assembly gets loaded. If I have a static webpage logging an user, and then render the first web assembly component, it reflects the the proper values. But if I have any component that triggers the web assembly runtime before the server authenticate the user, the web assembly AuthenticationStateProvider remains without any user identity forever.

From my components, I can inject a Task<AuthenticationState> with the [CascadingParameter] attribute, or an AuthenticationStateProvider and call GetAuthenticationStateAsync(). I can clearly see that if do it inside a static SSR component and check either, the value correctly represent my user at any moment. But if I do the same in a WASM component, it remains the same all the of application lifetime and reflect the value it was on the server when the first web assembly component got rendered.

I would really like to have the possibility to log in, and out log users while the web assembly runtime is active and have it get reflected. Even better, I would like to be able to subscribe to the AuthenticationStateChanged event. Is this possible?


Solution

  • I'll close this and mark this question as "cannot be done".

    At least not what I'm trying to achieve with the base Blazor solution stack from Microsoft, it would require a more advanced custom implementation.

    Justification:

    When creating the Blazor Web App template with .NET 9 and Authentication enabled, it uses AddAuthenticationStateSerialization/AddAuthenticationStateDeserialization. But when an user log in or out, it use a redirect which completely reload the page and reload the WASM assembly from scratch. Changing that behavior to use the NavigationManager redirect and I get the same behavior that the auth info doesn't refresh.

    When creating the Blazor Web App template with .NET 8, it actually includes the implementation doing the same in the PersistentAuthenticationStateProvider.cs file. On top of this file, we can find this unfortunate comment:

    This authentication state will be fixed for the lifetime of the WebAssembly application. So, if the user needs to log in or out, a full page reload is required.