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:
Add Permission
{ "id": 1, "resource": "api/Resources/Endpoints", // or "api/Resources/Endpoints/:id"... "method": "get" // or "post",... }Add permissions to role
Add roles to user
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:
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.
