I have Blazor Server solution on .NET 8. I am trying to implement Windows authorization and more or less is works but not completely the way I want. I do not have an idea how to fix that.
When I navigate to the page, let's say counter page, it works; if I refresh the page, it throws an error
Access to localhost was denied
You don't have authorization to view this page
HTTP ERROR 403
In Counter.razor I just added
@attribute [Authorize(Roles = "Admin")]This is Program.cs:
using BlazorAuth8;using BlazorAuth8.Components;using Microsoft.AspNetCore.Authentication.Negotiate;using Microsoft.AspNetCore.Components.Authorization;var builder = WebApplication.CreateBuilder(args);// Add services to the container.builder.Services.AddRazorComponents() .AddInteractiveServerComponents();builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme) .AddNegotiate();builder.Services.AddAuthorization(options =>{ // By default, all incoming requests will be authorized according to the default policy. options.FallbackPolicy = options.DefaultPolicy;});builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthenticationStateProvider>();var app = builder.Build();// Configure the HTTP request pipeline.if (!app.Environment.IsDevelopment()){ 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.UseHttpsRedirection();app.UseStaticFiles();app.UseAntiforgery();app.UseAuthentication();app.UseAuthorization();app.MapRazorComponents<App>() .AddInteractiveServerRenderMode();app.Run();CustomAuthenticationStateProvider.cs:
using Microsoft.AspNetCore.Components.Authorization;using Microsoft.AspNetCore.Components.Server;using System.Security.Claims;namespace BlazorAuth8.Components;public class CustomAuthenticationStateProvider : ServerAuthenticationStateProvider{ private const string LocalAdminGroupSid = "S-1-5-32-545"; private const string AdGroupClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid"; public override async Task<AuthenticationState> GetAuthenticationStateAsync() { var authState = await base.GetAuthenticationStateAsync(); var user = authState.User; // Adds a new Identity to the ClaimsPrincipal with the Group pset if (user.Claims.Any(claim => claim.Type == AdGroupClaimType && claim.Value == LocalAdminGroupSid)) user.AddIdentity(new ClaimsIdentity(new List<Claim>() { new Claim(ClaimTypes.Role, "Admin") })); // return the modified principal return await Task.FromResult(new AuthenticationState(user)); }}Routes.razor:
<CascadingAuthenticationState><Router AppAssembly="@typeof(Program).Assembly"><Found Context="routeData"><RouteView RouteData="@routeData" DefaultLayout="@typeof(Layout.MainLayout)" /><FocusOnNavigate RouteData="@routeData" Selector="h1" /></Found></Router></CascadingAuthenticationState>App.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="bootstrap/bootstrap.min.css" /><link rel="stylesheet" href="app.css" /><link rel="stylesheet" href="BlazorAuth8.styles.css" /><link rel="icon" type="image/png" href="favicon.png" /><HeadOutlet @rendermode="InteractiveServer" /></head><body><Routes @rendermode="InteractiveServer" /><script src="_framework/blazor.web.js"></script></body></html>Home.razor:
@page "/"@using System.Text<PageTitle>Home</PageTitle><h1>Hello, world!</h1><AuthorizeView> Hello, @context.User.Identity?.Name. Welcome to your new app.</AuthorizeView><div class="bg-dark text-white m-2 p-2"><pre>@_sb.ToString()</pre></div>@code { private StringBuilder _sb = new StringBuilder(); [CascadingParameter] private Task<AuthenticationState>? authenticationStateTask { get; set; } protected override async Task OnInitializedAsync() { ArgumentNullException.ThrowIfNull(authenticationStateTask, nameof(authenticationStateTask)); var authState = await authenticationStateTask; var user = authState.User; if (user?.Identity?.IsAuthenticated ?? false) { _sb.AppendLine($"User: {user.Identity.Name}"); foreach (var claim in user.Claims) { _sb.AppendLine($"Claim Type: {claim.Type}; Claim Value: {claim.Value}"); } } }}