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

Blazor Wasm JWT Authentication Issue .net 8

$
0
0

I have a .net 8 Blazor Wasm app which I am trying to add basic custom JWT authorisation to. (Users in our own db)

However when I go to the protected page it just shows screen with a 401 error. If I remove the authorize attribute the page works fine (although obviously not protected).

Here is the page

@page "/test"@using Microsoft.AspNetCore.Authorization@using Microsoft.AspNetCore.Components.Authorization@inject HttpClient Http@attribute [Authorize]<h3>Test</h3>@code {}

and the Routes.razor

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

and the Custom Authentication Provider

using Blazored.LocalStorage;using Microsoft.AspNetCore.Components;using Microsoft.AspNetCore.Components.Authorization;using System.Net.Http.Headers;using System.Security.Claims;using System.Text.Json;namespace Web.Client.Auth{    public class CustomAuthStateProvider : AuthenticationStateProvider    {        private readonly HttpClient _httpClient;        private readonly ILocalStorageService _localStorage;        private readonly NavigationManager _navigationManager;        private readonly AuthenticationState _anonymous;        private readonly JsonSerializerOptions _options;        public CustomAuthStateProvider(HttpClient httpClient, ILocalStorageService localStorage, NavigationManager navigationManager)        {            _httpClient = httpClient;            _localStorage = localStorage;            _navigationManager = navigationManager;            _anonymous = new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));            _options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };        }        public override async Task<AuthenticationState> GetAuthenticationStateAsync()        {            var token = await _localStorage.GetItemAsync<string>("authToken");            if (string.IsNullOrWhiteSpace(token))            {                return _anonymous;            }            var claims = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>(), "jwtAuthType"));            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", token);            //CheckTimeSinceLogin(claims);            return new AuthenticationState(claims);        }        public void NotifyUserAuthentication(string email)        {            var authenticatedUser = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, email) }, "jwtAuthType"));            var authState = Task.FromResult(new AuthenticationState(authenticatedUser));            NotifyAuthenticationStateChanged(authState);        }        public void NotifyUserLogout()        {            var authState = Task.FromResult(_anonymous);            NotifyAuthenticationStateChanged(authState);        }    }}

Here is the Program.cs for the client app

using Microsoft.AspNetCore.Components.WebAssembly.Hosting;using Microsoft.AspNetCore.Components.Authorization;using RecoWeb.Client.Auth;using Blazored.LocalStorage;var builder = WebAssemblyHostBuilder.CreateDefault(args);builder.Services.AddAuthorizationCore();builder.Services.AddCascadingAuthenticationState();builder.Services.AddHttpClient("VLA.ServerAPI", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress));builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });builder.Services.AddBlazoredLocalStorage();builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthStateProvider>();await builder.Build().RunAsync();

and for the server app

using Microsoft.AspNetCore.Authentication.JwtBearer;using Microsoft.AspNetCore.Components.Authorization;using Microsoft.EntityFrameworkCore;using Microsoft.IdentityModel.Tokens;using MyApp.DataService;using MyApp.DataService.Models;using MyApp.Interfaces;using MyApp.Services;using MyApp.Shared.Dtos;using MyAppWeb.Client.Auth;using MyAppWeb.Client.Pages;using MyAppWeb.Components;using MyAppWeb.Controllers;using StockDataImporter;using System.Text;var builder = WebApplication.CreateBuilder(args);var config = builder.Configuration;builder.Configuration.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);builder.Configuration.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true);builder.Configuration.AddJsonFile($"appsettings.local.json", optional: true);// Add services to the container.builder.Services.AddRazorComponents()    .AddInteractiveWebAssemblyComponents();builder.Services.AddControllers(); // Add this linebuilder.Services.AddRazorPages();builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>{    var jwtSettings = config.GetSection("JWTSettings");    options.TokenValidationParameters = new TokenValidationParameters    {        ValidateIssuer = true,        ValidateAudience = true,        ValidateLifetime = true,        ValidateIssuerSigningKey = true,        ValidIssuer = jwtSettings["validIssuer"],        ValidAudience = jwtSettings["validAudience"],        ClockSkew = new TimeSpan(0, 1, 0),        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings["securityKey"]))    };});builder.Services.AddDbContext<RecodbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")), ServiceLifetime.Transient);builder.Services.AddScoped<IDataService, DataService>();builder.Services.AddScoped<IStockDataImportService, StockDataImportService>();builder.Services.AddScoped<IPartService, PartService>();builder.Services.AddScoped<IStockService, StockService>();var app = builder.Build();// Configure the HTTP request pipeline.if (app.Environment.IsDevelopment()){    app.UseWebAssemblyDebugging();}else{    app.UseExceptionHandler("/Error", createScopeForErrors: true);    // 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.UseAuthentication();app.UseHttpsRedirection();app.UseStaticFiles();app.UseRouting(); // Add this lineapp.UseAntiforgery();app.UseAuthorization(); // Add this lineapp.MapControllers();app.MapRazorComponents<App>()    .AddInteractiveWebAssemblyRenderMode()    .AddAdditionalAssemblies(typeof(RecoWeb.Client._Imports).Assembly);app.Run();

What am I doing wrong?

Just to be clear, I am expecting the page to show the NotAuthorised content from the routes.razor.

It was never this hard in .net 7...


Viewing all articles
Browse latest Browse all 4839

Trending Articles



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