asp.net-coreauthenticationcookiesblazor-server-sidehttpcontext

Blazor (Interactive server) cookie authentication: user identity is lost after LocalRedirect from Razor page


i have a Blazor Server application that is relying on a third party Rest API to authenticate users, providing a token to be used with any HTTP call. Blazor side i implemented a custom authentication state provider to manage the user state and everything works fine. Now i need to implement two internal controllers (in the same project, they're needed for some component library i'm using) and this way they are not secured, so i was trying to pass through Cookie based authentication.

I managed to store the cookie in the browser and, as far as i can see, the cookie is being sent in the request towards Razor components. But if the page is marked with [Authroize] attribute (they all are) i'm just being redirected to the login page, by design. After checking it carefully i saw that the user Identity is completely lost once i redirect from the Razor page i'm using to access HttpContext to the Blazor component (and so authenticationState.User.Identity.IsAuthenticated is always false).

I've been through a lot of posts and documentation but i really can't figure out why. I'm providing some simplified code. Thanks for any tip.

LoginAuth.cshtml


public async Task<IActionResult> OnGetAsync(string u) {


     var claims = new List<Claim>
     {
         new Claim(ClaimTypes.Name, u),
     };
    
     var claimsIdentity = new ClaimsIdentity(
         claims, CookieAuthenticationDefaults.AuthenticationScheme);
    
     var authProperties = new AuthenticationProperties
     {
         IsPersistent = true,
     };
    
     await HttpContext.SignInAsync(
         CookieAuthenticationDefaults.AuthenticationScheme,
         new ClaimsPrincipal(claimsIdentity),
         authProperties);
    return LocalRedirect("/dashboard");
}

Login.razor

 private async Task Authenticate()
   {
       var result = await authenticationService.GetToken(user);
          if (result != null) {
    //storing some info inside session storage and updating the auth. state (this should be removed
//with a working Cookie auth i guess)
                             }
       navManager.NavigateTo($"/loginAuth?u={result.Username}",true);


   }

Program.cs

builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(options =>
    {
        options.ExpireTimeSpan = TimeSpan.FromMinutes(20);  
        options.SlidingExpiration = true;
        options.LoginPath = "/login";
        options.Cookie.HttpOnly = true;  
        options.Cookie.SameSite = SameSiteMode.Lax;  
        options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
    });

Solution

  • I found the problem: i was previously using a CustomAuthenticationStateProvider and i forgot to remove it from the application builder:

    builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthenticationStateProvider>();
    

    This is overwriting, as inteded i guess, any other state coming from a different authentication flow.