1

I did see this stackoverflowQuestion but this revolves around using the, Authorize attribute. I am using a custom authorize attribute, by extending AuthorizeAttribute.

I want to be able to place this custom filter at the top level of the controller class, but for a couple of methods enforce only a specific role, not both the top level and action method role.

so,

[AuthorizeUser("Transact")]
public class HomeController : Controller
{
    //
    // GET: /Search/Home/

    public ActionResult Index()
    { 
        return View();
    }

    [AuthorizeUser("Search")]
    public ActionResult Search()
    { 
        return View();
    }

}

Doing this, the framework will check to see if a user has both the Transact, and Search role.. I just want to check for the search role in this scenario.

I am reusing this search functionality and partialview in another Area.

eaglei22
  • 2,589
  • 1
  • 38
  • 53

2 Answers2

1

Going back to the link I posted: stackoverflowQuestion I was able to make it work in my situation. What seems to be happening is the call to my action first looks at the attribute from the Controller level, but using filterContext.ActionDescriptor.IsDefined inside the OnAuthroization method will tell me if the called action has my override attribute attached. If it does it skips calling the base.OnAuthorization method, then the override attribute will be invoked.

So, what I had to do was create the override class and extend my custom authorization class. I have a flag declared in the parent and set in the override class's constructor to tell me if the override authorization method is calling the authorization methods of my custom authorization class.

Here is the example to make sense of it all.

public class AuthorizeUserAttribute : AuthorizeAttribute
{
    protected bool isOverrideAuthorize = false;

    public AuthorizeUserAttribute(params...)
    {
    }

    public AuthorizeUserAttribute(MenuItems...)
    {
    }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        var action = filterContext.ActionDescriptor;
        if (action.IsDefined(typeof(OverrideAuthorizeUserAttribute), true) && !isOverrideAuthorize)
        {
            return;
        }

        base.OnAuthorization(filterContext);
    }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {

    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
    }
  }

The override class:

public class OverrideAuthorizeUserAttribute : AuthorizeUserAttribute
{
    public OverrideAuthorizeUserAttribute(params...) : base(roles)
    {
        base.isOverrideAuthorize = true;
    }

    public OverrideAuthorizeUserAttribute(MenuItems...) : base(item)
    {
        base.isOverrideAuthorize = true;
    }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        return base.AuthorizeCore(httpContext);
    }
}

This allowed me to do authorization on the action solely on the authorization attribute declared on that action, rather than the authorization attribute on the controller AND action method, as defaulted by the framework.

Also, MVC5 seems to have this problem covered by including a, "OverrideAuthorization" attribute.. Unfortunately I am still on MVC4.

eaglei22
  • 2,589
  • 1
  • 38
  • 53
0

You can try at the top of controller like bellow this will support multiple role for single controller or you can use same Authorize(Roles = "Admin") filter top of every action....

[Authorize(Roles = "Admin,HRManager,Finance")]
Public class MyController:Controller{

  // inside controller action methods
 }
Zahidul
  • 76
  • 5