5

I started off using the default project's AccountController, but I've extended/changed it beyond recognition. However, in common with the original I have a LogOn and LogOff action.

Clearly, the LogOn action must be accessible to everyone. However, since I've added lots of other actions to this controller (to create & edit users), I want 99% of the actions to require administrator role membership.

I could decorate all my actions with [Authorize Roles="Administrators"] but there's a risk I'll forget one. I'd rather make it secure by default, by decorating the controller class itself with that attribute, and then relax the requirement on my LogOn method. Can I do that?

(As in, can I do that out-of-the-box without creating custom classes, etc. I don't want to complicate things more than necessary.)

Gary McGill
  • 26,400
  • 25
  • 118
  • 202

3 Answers3

4

To override an controller Attribute at the Action level you have to create a custom Attribute and then set the Order property of your custom attribute to a higher value than the controller AuthorizeAttribute. I believe both attributes are then still executed unless your custom attribute generates a result with immediate effect such as redirecting.

See Overriding controller AuthorizeAttribute for just one action for more information.

So I believe in your case you will just have to add the AuthorizeAttribute on the Actions and not at the controller level. You could however create a unit test to ensure that all Actions (apart from LogOn) have an AuthorizeAttribute

Community
  • 1
  • 1
David Glenn
  • 24,412
  • 19
  • 74
  • 94
2

After way too much time, I came up with a solution.

public class OverridableAuthorize : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        var action = filterContext.ActionDescriptor;
        if(action.IsDefined(typeof(IgnoreAuthorization), true)) return;

        var controller = action.ControllerDescriptor;
        if(controller.IsDefined(typeof(IgnoreAuthorization), true)) return;

        base.OnAuthorization(filterContext);
    }
}

Which can be paired with IgnoreAuthorization on an Action

public class IgnoreAuthorization : Attribute
{
}
bmavity
  • 2,477
  • 2
  • 24
  • 23
2

You can use AuthorizeAttribute on your class

http://msdn.microsoft.com/en-us/library/system.web.mvc.authorizeattribute.aspx

For relaxing you can implement for example a custom action filter attribute like this (I didn' test if it works).

public class GetRidOfAutorizationAttribute : AuthorizeAttribute 
{
public override void OnAuthorization(AuthorizationContext filterContext)
{

// you can for example do nothing
filterContext.Result = new EmptyResult(); 

}
}
Tomasz Jaskuλa
  • 15,723
  • 5
  • 46
  • 73