To create a custom authorization attribute in a Blazor application that checks user roles against a database, follow these steps:
Create a Custom Authorization Attribute:
You can create a custom attribute by implementing IAuthorizationFilter
or using middleware logic. This attribute will query the database to verify the user's role.
public class DbRoleAuthorizeAttribute : AuthorizeAttribute, IAsyncAuthorizationFilter { private readonly string[] _roles; public DbRoleAuthorizeAttribute(params string[] roles) { _roles = roles; } public async Task OnAuthorizationAsync(AuthorizationFilterContext context) { var httpContext = context.HttpContext; var user = httpContext.User; if (!user.Identity?.IsAuthenticated ?? true) { // User is not authenticated context.Result = new Microsoft.AspNetCore.Mvc.ForbidResult(); return; } var userIdClaim = user.Claims.FirstOrDefault(c => c.Type == "UserId")?.Value; if (string.IsNullOrEmpty(userIdClaim)) { context.Result = new Microsoft.AspNetCore.Mvc.ForbidResult(); return; } // Inject your DbContext service var dbContext = httpContext.RequestServices.GetService(typeof(YourDbContext)) as YourDbContext; if (dbContext == null) { throw new InvalidOperationException("DbContext is not available."); } // Query the database for roles var userRoles = await dbContext.UserRoles .Where(ur => ur.UserId == Guid.Parse(userIdClaim)) .Select(ur => ur.Role.Name) .ToListAsync(); if (!_roles.Any(role => userRoles.Contains(role))) { // User does not have the required role context.Result = new Microsoft.AspNetCore.Mvc.ForbidResult(); } } }
Apply the Custom Attribute to Razor Pages or Methods:
@page @attribute [DbRoleAuthorize("Admin", "Manager")] <h3>Restricted Content</h3> <p>Only users with Admin or Manager roles can see this.</p>
@page @attribute [Authorize] @code { [DbRoleAuthorize("Editor")] public void HandleEditorContent() { // Logic for Editor-only content } }
Configure Database Context in Program.cs
or Startup.cs
Make sure the database context (YourDbContext
) is registered in your application.
builder.Services.AddDbContext<YourDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); builder.Services.AddAuthorization(); builder.Services.AddAuthentication("YourAuthenticationScheme") .AddCookie("YourAuthenticationScheme", options => { options.LoginPath = "/Login"; });
Update the Database Model:
Ensure you have a database model for roles and user-role relationships.
public class Role { public Guid Id { get; set; } public string Name { get; set; } } public class UserRole { public Guid UserId { get; set; } public Guid RoleId { get; set; } public Role Role { get; set; } }
Test Your Implementation
Log in with a user and assign roles in the database. Verify that the attribute correctly allows or denies access based on the database role check.
This approach ensures dynamic, database-driven role authorization in your Blazor app while maintaining flexibility and scalability.