Description
This is for server-side Blazor and will address most of the issues with using Windows authentication.
Currently the built-in internal default FixedAuthenticationStateProvider
assumes the authentication state is fixed for the lifetime of the circuit, as its name implies. However this isn't adequate for Windows authentication, as the WindowsPrincipal
is connected to underlying OS services and can't continue to be used if the original HTTP request has completed. Trying to call things like IsInRole
will throw if the principal has already been disposed, which would happen if:
- You're using prerendering, in which case the original WindowsPrincipal will have been disposed once the prerendering HTTP request completed
- Even if you're not using prerendering, if the WebSocket connection was ever lost, or if you're using something else like long polling where the original request isn't retained anyway
To resolve this, we need some extra logic that, whenever the circuit connection becomes up (equivalent to OnConnectionUpAsync
on a circuit handler), we grab the latest User
from the HubContext
(or HttpContext
if we must, but HubContext
is more correct) and pass it to the built-in authentication state provider, which can update its own internal state and call its own NotifyAuthenticationStateChanged
.
Caveat
This will fix most scenarios, but one case will remain: if the user is currently disconnected and some background process is trying to call APIs like IsInRole
on their ClaimsPrincipal
, this will still throw. There's nothing we can do about that short of adding features at the IIS integration layer, which would have other drawbacks so we might never want to do that. Basically, developers should only be using Windows authentication for intranet apps where transient disconnection is not something that will happen, or they do their own error handling if it does.