How to implement ACLs (Access Control List ) in ASP.NET Core 8.0

43 views Asked by At

I'm developing an ASP.NET Core 8.0 application and I need to implement Access Control Lists (ACLs) to manage user access rights. Currently, I'm using policies to check if the user's roles have permission for the resource being accessed. However, I'm wondering if my approach is correct or if there's a better way to do it.

Here's what I'm currently doing:

  1. Add Permission

    {
        "id": 1,
        "resource": "api/Resources/Endpoints", // or "api/Resources/Endpoints/:id"...
        "method": "get" // or "post",...
    }
    
  2. Add permissions to role

  3. Add roles to user

  4. Get role from JWT claims to check permission resource

I have this in Program.cs:

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("ACLs", policy =>
        policy.RequireAssertion(async context =>
        {
            var canAccess = false;
            var httpContext = context.Resource as HttpContext;

            // get method
            var method = httpContext.Request.Method.ToString();
            // get endpoint /api/controller/...
            var endpoint = httpContext.GetEndpoint();
            var routePattern = (endpoint as RouteEndpoint)?.RoutePattern;
            var endpointValue = "";

            // convert endpoint from /api/{id}/... to /api/:id to match resource in permission
            if (routePattern != null)
            {
                endpointValue = routePattern.RawText;
            }

            if (httpContext.User.Identity.IsAuthenticated)
            {
                // get dbContext from httpContext
                var dbContext = httpContext.RequestServices.GetRequiredService<Context>();
                // get roleClaims and check role can access endpoint
                var roleClaims = httpContext.User.Claims.Where(claim => claim.Type == ClaimTypes.Role);

                foreach (var claim in roleClaims)
                {
                    if (canAccess)
                        break;

                    var roleName = claim.Value;
                    var roleEntity = dbContext.roles.Include(role => role.Permissions).FirstOrDefault(role => role.Name == roleName);

                    foreach (var permission in roleEntity.Permissions)
                    {
                        if (permission.Resource == StringConverter.ConvertToColonFormat(endpointValue) && MethodConverter.ConvertToString(permission.Method).ToLower() == method.ToLower())
                        {
                            canAccess = true;
                            break;
                        }
                    }
                }
            }
            return canAccess;
        }));
});

In the controller:

enter image description here

I'm unsure if this approach is the most efficient or if there are better practices for implementing ACLs in ASP.NET Core 8.0. I would appreciate any guidance, insights, or alternative approaches that the community can offer.

Thank you.

0

There are 0 answers