I have the similar code working in previous version like .NET 7, but I get "HTTP ERROR 401" error, when I add @attribute [Authorize] to the page.
Here is the sample project in GIT hub.
https://github.com/sbakula/BlazorServerCustomAuthTest
My Program.cs code;
using BlazorServerCustomAuthTest.Auth;using BlazorServerCustomAuthTest.Components;using Microsoft.AspNetCore.Authentication.JwtBearer;using Microsoft.AspNetCore.Components.Authorization;using Microsoft.IdentityModel.Tokens;using System.Text;var builder = WebApplication.CreateBuilder(args);builder.Services.AddAuthentication(options =>{ options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;}) .AddJwtBearer(options => { options.SaveToken = true; options.RequireHttpsMetadata = false; options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters() { ValidateIssuer = true, ValidateAudience = true, ValidAudience = "XXXX", ValidIssuer = "XXXX", IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("XXXX")) }; });// Add services to the container.builder.Services.AddRazorComponents() .AddInteractiveServerComponents();builder.Services.AddScoped<AuthStateProvider>();builder.Services.AddScoped<AuthenticationStateProvider, AuthStateProvider>( provider => provider.GetRequiredService<AuthStateProvider>() );builder.Services.AddScoped<ILoginService, AuthStateProvider>( provider => provider.GetRequiredService<AuthStateProvider>() );var app = builder.Build();// Configure the HTTP request pipeline.if (!app.Environment.IsDevelopment()){ app.UseExceptionHandler("/Error", createScopeForErrors: true); app.UseHsts();}app.UseHttpsRedirection();app.UseStaticFiles();app.UseRouting();app.UseAuthentication();app.UseAuthorization();app.UseAntiforgery();app.MapRazorComponents<App>() .AddInteractiveServerRenderMode();app.Run();Routes.razor code:
<Router AppAssembly="typeof(Program).Assembly"><Found Context="routeData"><AuthorizeRouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)"><NotAuthorized><text>Custom not authorized...</text></NotAuthorized></AuthorizeRouteView><FocusOnNavigate RouteData="routeData" Selector="h1" /></Found></Router>My AuthStateProvider.cs:
using Microsoft.AspNetCore.Components.Authorization;using System.Net.Http.Headers;using System.Security.Claims;using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage;using BlazorServerCustomAuthTest.Models;namespace BlazorServerCustomAuthTest.Auth{ public class AuthStateProvider : AuthenticationStateProvider, ILoginService { private ProtectedSessionStorage ProtectedSessionStore; static AuthenticationState Anonymous => new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity())); public AuthStateProvider(ProtectedSessionStorage ProtectedSessionStore) { this.ProtectedSessionStore = ProtectedSessionStore; } public async override Task<AuthenticationState> GetAuthenticationStateAsync() { UserProfile? user; var result = await ProtectedSessionStore.GetAsync<UserProfile>("UserProfile"); if (result.Success) { user = result.Value; return await Task.FromResult(BuildAuthenticationState(user)); } else { return Anonymous; } } public async Task Login(UserProfile user) { await ProtectedSessionStore.SetAsync("UserProfile", user); var authState = BuildAuthenticationState(user); NotifyAuthenticationStateChanged(Task.FromResult(authState)); } public async Task Logout() { await ProtectedSessionStore.DeleteAsync("UserProfile"); NotifyAuthenticationStateChanged(Task.FromResult(Anonymous)); NotifyAuthenticationStateChanged(GetAuthenticationStateAsync()); } static AuthenticationState BuildAuthenticationState(UserProfile? userProfile) { if (userProfile is null) { return Anonymous; } else { var claims = new List<Claim> { }; claims.Add(new Claim(ClaimTypes.Name, userProfile.UserName)); return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(claims, "jwt"))); } } }}ILoginService.cs:
using BlazorServerCustomAuthTest.Models;namespace BlazorServerCustomAuthTest.Auth{ public interface ILoginService { Task Login(UserProfile user); Task Logout(); }}_Imports.razor:
@using System.Net.Http@using System.Net.Http.Json@using Microsoft.AspNetCore.Components.Forms@using Microsoft.AspNetCore.Components.Routing@using Microsoft.AspNetCore.Components.Web@using static Microsoft.AspNetCore.Components.Web.RenderMode@using Microsoft.AspNetCore.Components.Web.Virtualization@using Microsoft.JSInterop@using BlazorServerCustomAuthTest@using BlazorServerCustomAuthTest.Components@using Microsoft.AspNetCore.Authorization@using Microsoft.AspNetCore.Components.AuthorizationApp.razor:
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><base href="/" /><link rel="stylesheet" href="app.css" /><link rel="stylesheet" href="BlazorServerCustomAuthTest.styles.css" /><HeadOutlet @rendermode="new InteractiveServerRenderMode( prerender: false )" /></head><body><Routes @rendermode="new InteractiveServerRenderMode( prerender: false )" /><script src="_framework/blazor.web.js"></script></body></html>