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?