Home > Enterprise >  Dynamic Role based Authorization in Blazor Server
Dynamic Role based Authorization in Blazor Server

Time:01-01

I'm new to blazor server. I have implemented asp.net core identity role-based authorization. But I don't want to hardcode roles on the Authorize attribute. I want to create roles later and specify in which controller and action it has access without touching source code.

enter image description here

As you can see in the image above how can I create dynamic role based authorization in blazor server

CodePudding user response:

You need to implement and Authorize via a policy.

You can create a permission that can be assigned to any Role. In combination with a Policy that checks for the permission.

This allows you to create roles at runtime and assign permissions to these new roles. When a user is then assigned a role the policy will see the permissions attached to the role.

Docs

Your screen would become groupings of 6 permissions that would be assigned to each role. Which would require 6 Policies.

I would consider using a class like the following:

Permission.cs

public sealed class Permission
{
    public static readonly IReadOnlyList<Permission> Permissions = new List<Permission>
    { RolesView, RolesCreate, RolesUpdate, RolesDelete, UserRoleView, UserRoleUpdate };

    public static explicit operator string(Permission p) => p.Key;

    public static Permission RolesView => new Permission
    {
        Key = "Permission.Roles.View",
        Display = "Role List",
        GroupName = "Role Management"
    };
    public static Permission RolesCreate => new Permission
    {
        Key = "Permission.Roles.Create",
        Display = "Create Role",
        GroupName = "Role Management"
    };
    public static Permission RolesUpdate => new Permission
    {
        Key = "Permission.Roles.Update",
        Display = "Edit Role",
        GroupName = "Role Management"
    };
    public static Permission RolesDelete => new Permission
    {
        Key = "Permission.Roles.Delete",
        Display = "Delete",
        GroupName = "Role Management"
    };
    public static Permission UserRoleView => new Permission
    {
        Key = "Permission.UserRole.View",
        Display = "User List",
        GroupName = "User Role Management"
    };
    public static Permission UserRoleUpdate => new Permission
    {
        Key = "Permission.UserRole.Update",
        Display = "Edit User Roles",
        GroupName = "User Role Management"
    };

    public string Key { get; private set; }
    public string Display { get; private set; }
    public string GroupName { get; private set; }
}


services.AddAuthorization(options =>
{
    ...
    options.AddPolicy(name: "UserRoleView", policy =>
            policy.RequireClaim(Permission.UserRoleView));
    ...
});

[Authorize(Policy = "UserRoleView")]

Use the RoleManagers methods AddClaimAsync & RemoveClaimAsync using the Permission as the claim exploiting the explicit string conversion.

CodePudding user response:

As an add on to Brian's answer, there's a PolicyBuilder factory that you can use to build out your policies. Here's a simple example from one of my applications:

public static class AppPolicies
{
    public const string IsAdmin = "IsAdmin";
    public const string IsUser = "IsUser";
    public const string IsVisitor = "IsVisitor";

    public static AuthorizationPolicy IsAdminPolicy
        => new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .RequireRole("Admin")
        .Build();

    public static AuthorizationPolicy IsUserPolicy
        => new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .RequireRole("Admin", "User")
        .Build();

    public static AuthorizationPolicy IsVisitorPolicy
        => new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .RequireRole("Admin", "User", "Visitor")
        .Build();

    public static Dictionary<string, AuthorizationPolicy> Policies
    {
        get
        {
            var policies = new Dictionary<string, AuthorizationPolicy>();
            policies.Add(IsAdmin, IsAdminPolicy);
            policies.Add(IsUser, IsUserPolicy);
            policies.Add(IsVisitor, IsVisitorPolicy);
            return policies;
        }
    }
}

And use it like this:

        services.AddAuthorization(config =>
        {
            foreach (var policy in AppPolicies.Policies) 
            {
                config.AddPolicy(policy.Key, policy.Value);
            }
        });
  • Related