I also had came across this issue when moving my Blazor Server App to .NET 8. So after many hours scratching my head I found a solution that I hope helps someone else down the track.
The way around it was for me to create a custom AuthenticationHandler
that essentially returns an authorised claim for every new request. It seems that the ASP Core part of Blazor requires an initial claims authentication method on the connection of each new HTTP request but after that, Blazor only uses AuthenticationStateProvider
to check if you can access components/pages with the [Authorize]
attribute. So if you just automatically authorise all initial connections then spin your own AuthenticationStateProvider
you get the required custom authentication for your application.
So what I did was create my own auth handler class:
public class CustomAuthenticationHandler(IOptionsMonitor<CustomAuthOptions> options, ILoggerFactory logger, UrlEncoder encoder,IHttpContextAccessor httpContextAccessor)
: AuthenticationHandler<CustomAuthOptions>(options, logger, encoder)
{
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
return AuthenticateResult.Success(new AuthenticationTicket(new ClaimsPrincipal(new GenericIdentity("CustomIdentity")), "CustomAuthenticationScheme"));
}
}
public class CustomAuthOptions : AuthenticationSchemeOptions
{
// Add any custom options here if needed in the future
}
Then add it as the the default Authentication Scheme in program.cs
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = "CustomScheme";
options.DefaultChallengeScheme = "CustomScheme";
})
.AddScheme<CustomAuthOptions, CustomAuthenticationHandler>("CustomScheme", options => { });
This gets around the error and lets you use your custom authentication via AuthenticationStateProvider
. And even though the code "authorises" all initial connections it does not allow access to any pages/components marked with the [Authorize]
attribute as that only uses the AuthenticationStateProvider
now.
Just for completelness, I add my custom AuthenticationStateProvider into program.cs as such:
builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthenticationProvider>();
Which in my case checks if a token has been set for the current user's circuit to say they are logged in - which happens on the login page. So far all my testing is working as expected with users only being able to access my secure pages when logged in correctly.
Again, hopefully that helps someone else out.