Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Role based authorization in ASP.NET Core 3: how to grant access everywhere to certain role?

I am writing a ABAC system in which I will decide if a user can access to certain data based on some roles/attributes/etc. However, there is a special kind of user (something like super-administrator) who should be able to access everything, everywhere, always. I don't want to go through all policies, controllers, actions and methods and add a check on this specific role. Is there a way to do it in a more centralized way? (for example: in the startup).

If it is not possible to add it to a global place, I was thinking on adding it at least globally on a controller level: I was looking here and I saw that the decorator [Authorize(Roles = "Administrator")] lets you restrict the access to a certain method/class just to Administrator users. However, I want kind of "the opposite". I mean something like an AuthorizeAlways that had the following behaviour:

[AuthorizeAlways(Roles = "SuperAdministrator")]
public class ControlPanelController : Controller
{
    [Authorize(Roles = "SetterUser")]
    public ActionResult SetTime()
    {
    }

    [Authorize(Roles = "PowerUser")]
    [MinimumAgeAuthorize(50)]
    public ActionResult ShutDown()
    {
    }
}

In this case I'd like that SuperAdministrator (even if they are 49 years old) has access to everywhere. A SetterUser has access only to SetTime and only a PowerUser who is older than 50 years old can access ShutDown.

I don't know if this makes much sense. Is it possible? Where could I do it? Thanks!

like image 226
xavier Avatar asked Sep 06 '25 03:09

xavier


1 Answers

This blog post provides a good tutorial for how to implement custom authorization: https://seanspaniel.wordpress.com/2019/12/13/custom-authorization-in-asp-net-core-3/

From that tutorial, in the CustomAuthorizationMiddleware class you could check for the "SuperAdministrator" role and grant access to every endpoint.

public static class CustomAuthorizationMiddleware
{
    public static async Task Authorize(HttpContext httpContext, Func next)
    {
        var endpointMetaData = httpContext.GetEndpoint().Metadata;

        bool hasCustomAuthorizeAttribute = endpointMetaData.Any(x => x is CustomAuthorizeAttribute);

        if (!hasCustomAuthorizeAttribute)
        {
            await next.Invoke();
            return;
        }

        CustomAuthorizeAttribute customAuthorizeAttribute = endpointMetaData
                .FirstOrDefault(x => x is CustomAuthorizeAttribute) as CustomAuthorizeAttribute;

        // Check if user has allowed role or super administrator role
        bool isAuthorized = customAuthorizeAttribute.AllowedUserRoles
            .Any(allowedRole => httpContext.User.IsInRole(allowedRole)) 
             || httpContext.User.IsInRole("SuperAdministrator");

        if (isAuthorized)
        {
            await next.Invoke();
            return;
        }

        httpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
        await httpContext.Response.WriteAsync("unauthorized");
    }
}
like image 187
sspaniel Avatar answered Sep 09 '25 17:09

sspaniel