// Authorization/PermissionAuthorizationHandler.cs using Microsoft.AspNetCore.Authorization; using System.Security.Claims; namespace Web.Authorization { public class PermissionRequirement : IAuthorizationRequirement { public string Permission { get; } public PermissionRequirement(string permission) { Permission = permission; } } public class PermissionAuthorizationHandler : AuthorizationHandler { protected override Task HandleRequirementAsync( AuthorizationHandlerContext context, PermissionRequirement requirement) { if (context.User == null || !context.User.Identity.IsAuthenticated) { return Task.CompletedTask; } // Admin role bypasses all permission checks if (context.User.IsInRole("Admin")) { context.Succeed(requirement); return Task.CompletedTask; } // Check if user has the required permission claim var hasPermission = context.User.Claims .Any(c => c.Type == Permissions.ClaimType && c.Value == requirement.Permission); if (hasPermission) { context.Succeed(requirement); } return Task.CompletedTask; } } // This provider auto-creates policies for every permission public class PermissionPolicyProvider : IAuthorizationPolicyProvider { private readonly DefaultAuthorizationPolicyProvider _fallbackProvider; public PermissionPolicyProvider(Microsoft.Extensions.Options.IOptions options) { _fallbackProvider = new DefaultAuthorizationPolicyProvider(options); } public Task GetPolicyAsync(string policyName) { // If the policy name matches a known permission, create a policy for it var allPermissions = Permissions.GetAll(); if (allPermissions.Contains(policyName)) { var policy = new AuthorizationPolicyBuilder() .RequireAuthenticatedUser() .AddRequirements(new PermissionRequirement(policyName)) .Build(); return Task.FromResult(policy); } return _fallbackProvider.GetPolicyAsync(policyName); } public Task GetDefaultPolicyAsync() { return _fallbackProvider.GetDefaultPolicyAsync(); } public Task GetFallbackPolicyAsync() { return _fallbackProvider.GetFallbackPolicyAsync(); } } }