Quantcast
Channel: Active questions tagged blazor - Stack Overflow
Viewing all articles
Browse latest Browse all 4839

Why doesn't cookie authentication work in my Blazor .NET 8 app?

$
0
0

I've been having trouble trying to set up simple authentication/authorization for my web app. Currently I have auth page

@page "/auth"@rendermode InteractiveServer@using System.Text.RegularExpressions@using System.ComponentModel.DataAnnotations@inject IHttpClientFactory HttpClientFactory@inject NavigationManager Navigation...@code {    ...    private async Task LoginAsync()    {        await form.Validate();        if (!success) return;        var client = HttpClientFactory.CreateClient("server");        var content = new FormUrlEncodedContent(new Dictionary<string, string>        {            { "email", loginEmail },            { "password", loginPassword }        });        var response = await client.PostAsync("api/auth/login", content);        if (!response.IsSuccessStatusCode)        {            errors = new[] { "Неверныйадресэл. почтыилипароль" };            return;        }        Navigation.NavigateTo("/", true);    }}

As you can see, I'm using http client to send post requests to auth controller. Here's how the controller looks like

[ApiController][Route("api/auth")]public class AuthController : Controller{    private readonly BarberchainDbContext _db;    public AuthController(BarberchainDbContext db)    {        _db = db;    }    [HttpPost]    [Route("login")]    public async Task<IActionResult> Login([FromForm] string email, [FromForm] string password)    {        var acc = _db.Accounts.FirstOrDefault(a => a.Email == email);        if (acc == null)        {            return BadRequest("Invalid login or email");        }        var hashString = System.Text.Encoding.UTF8.GetString(acc.Hash);        if (!BCrypt.Net.BCrypt.Verify(password, hashString))        {            return BadRequest("Invalid login or email");        }        var claims = new List<Claim>        {            new Claim(ClaimTypes.NameIdentifier, acc.Id.ToString()),            new Claim(ClaimTypes.Name, acc.Email ?? ""),            new Claim(ClaimTypes.Role, acc.Role.ToString())        };        var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);        var principal = new ClaimsPrincipal(identity);        await HttpContext.SignInAsync(            CookieAuthenticationDefaults.AuthenticationScheme,            principal,            new AuthenticationProperties            {                IsPersistent = true,                ExpiresUtc = DateTimeOffset.UtcNow.AddDays(7)            }        );        return Ok();    }    ...}

In Routes.razor I have this:

@using barberchainAPI.Components.Layout@using Microsoft.AspNetCore.Components.Authorization<Router AppAssembly="typeof(Program).Assembly"><Found Context="routeData"><AuthorizeRouteView RouteData="routeData" DefaultLayout="typeof(MainLayout)" /><FocusOnNavigate RouteData="routeData" Selector="h1" /></Found></Router>

Notice AuthorizeRouteView - it was previously just RouteView. This change I found in one of tutorials. In fact, I tried many things to get it to work. Finally, and I hope it's not too much code, Program.cs

public static void Main(string[] args){    var builder = WebApplication.CreateBuilder(args);    builder.Services.AddRazorPages();    builder.Services.AddRazorComponents()        .AddInteractiveServerComponents();    builder.Services.AddDbContext<BarberchainDbContext>(options => options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection"),        o => o.MapEnum<AccountRole>("account_role")));    builder.Services.AddMudServices();    builder.Services.AddControllers();    builder.Services.AddHttpClient("server", client =>    {        client.BaseAddress = new Uri("https://localhost:7027/");    });    builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)        .AddCookie(x =>        {            x.LoginPath = "/auth";        });    builder.Services.AddAuthorization();    builder.Services.AddCascadingAuthenticationState();    builder.Services.AddScoped<LocalStorageService>();    builder.Services.AddScoped<CartService>();    var app = builder.Build();    // Configure the HTTP request pipeline.    if (!app.Environment.IsDevelopment())    {        app.UseExceptionHandler("/Error");        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.        app.UseHsts();    }    app.UseHttpsRedirection();    app.UseStaticFiles();    app.UseRouting();    app.UseAuthentication();    app.UseAuthorization();    app.UseAntiforgery();    app.MapControllers();    app.MapRazorComponents<barberchainAPI.Components.App>()        .AddInteractiveServerRenderMode();    app.Run();}

The problem is that when I login, I get redirected to the home page ("") - which is just how it should be - and when I access account page the claims list is empty and so authorization logic doesn't work. The claims are set in "\login" endpoint of my auth controller.

Notice how AuthPage.razor uses @rendermode InteractiveServer. I looked at a similar question here on stack overflow and the person that replied said that the rendermode should be static SSR (static server side rendering I guess). Rendermode "InteractiveServer" is apparently the opposite. However, when I remove the rendermode (I assume it's SSR when it's not specified) the page becomes static and buttons don't react to my clicks. Maybe this @rendermode directive is what causes all the trouble due to specifics of InteractiveServer rendermode. Maybe I should switch to other rendermode? To which one? Why?


Viewing all articles
Browse latest Browse all 4839

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>