Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.netcore override controllerlevel Authorizeattribute on single action method

In the controllercode below only users who are in the "Administrator" role can accesss the GetData() action method, because of the controllerlevel Authorizeattribute. But I also want users who only are in "Manager" role to have access to the GetData() action method, how to write a custom attribute for this?

[Authorize(Roles = "Administrator")]
Pulic class AdminController : Controller
{

[Authorize(Roles = "Administrator, Manager")]
public IActionResult GetData()
{
}

}
like image 780
David Lenn Avatar asked Apr 11 '26 22:04

David Lenn


2 Answers

The class-level attribute is always checked first, so it denies anyone who is not in the right role. You need to specify the widest access at class level, then narrow it down on method level where needed:

[Authorize(Roles = "Administrator, Manager")]
public class AdminController : Controller
{
    // no attribute needed here
    public IActionResult GetData()
    {
    }

    [Authorize(Roles = "Administrator")]
    public IActionResult RestrictedMethod()
    {
    }
}
like image 161
Peter B Avatar answered Apr 13 '26 12:04

Peter B


In the startup.cs file, add the Authorization as follows:

services.AddAuthorization(options =>
        {
            var roles = new List<string>{ Role.Administrator, Role.Manager};

            var requirement =
                new List<IAuthorizationRequirement> {new AdminManagerAuthorizationOverrideOthers(roles) };
            var sharedAuthentication =
                new AuthorizationPolicy(requirement,
                    new List<string>());
            options.AddPolicy(name: "AdminManager", policy: sharedAuthentication);
            options.AddPolicy(name: "Administrator", configurePolicy: policy => policy.RequireAssertion(e =>
            {
                if (e.Resource is AuthorizationFilterContext afc)
                {
                    var noPolicy = afc.Filters.OfType<AuthorizeFilter>().Any(p =>
                        p.Policy.Requirements.Count == 1 &&
                        p.Policy.Requirements.Single() is AdminManagerAuthorizationOverrideOthers);
                    if (noPolicy)
                        return true;
                }
                return e.User.IsInRole(Role.Administrator);
            }));

        });

Create a class in any namespace that Inherits "RolesAuthorizationRequirement" from "Microsoft.AspNetCore.Authorization.Infrastructure" namespace as follows:

public class AdminManagerAuthorizationOverrideOthers : RolesAuthorizationRequirement
{
    public AdminManagerAuthorizationOverrideOthers(IEnumerable<string> allowedRoles) : base(allowedRoles)
    {
    }
}

Then, decorate the controller and action method as follows:

[Authorize(Policy = "Administrator")]
Public class AdminController : Controller
{
    public IActionResult GetData()
    {
    }

    [Authorize(Policy = "AdminManager")]
    public IActionResult AdministratorOnly()
    {
    }
}
like image 43
Pravin Avatar answered Apr 13 '26 11:04

Pravin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!