Attribute inheriting from AuthorizeAttribute not working
Asked Answered
A

1

6

I'm currently trying to implement security in a new ASP MVC 5 application, based on user roles. The goal is to prevent users from accessing certain controllers or controller methods if they don't have a certain role (or higher). Based on what I've read on the question so far, I created an attribute that inherits AuthorizeAttribute which looks like this (MyAppRole is an enum, btw) :

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class AuthorizeRoleOrSuperiorAttribute : AuthorizeAttribute
{
    private MyAppRole _authorizedRole;

    public AuthorizeRoleOrSuperiorAttribute(MyAppRole authorizedRole)
    { //Breakpoint here
        _authorizedRole = authorizedRole;
    }

    public override void OnAuthorization(HttpActionContext actionContext)
    { //Breakpoint here
        base.OnAuthorization(actionContext);

        if (!UserInfo.GetUserRoles().Any(r => (int)r >= (int)_authorizedRole))
            throw new UnauthorizedAccessException(ErrorsModule.RoleMissing);
    }
}

And I call it this way on methods and/or controllers :

[AuthorizeRoleOrSuperior(MyAppRole.Admin)]
public class MyController : Controller
{
    [AuthorizeRoleOrSuperior(MyAppRole.Admin)]
    public ViewResult Index()
    {
        [...]
    }

    [...]
}

I placed a breakpoint on the constructor and the OnAuthorization method but, when I launch the app and call the concerned controller or method, I never hit any of them and the action is called, even though I'm not even logged in.

Note : the AuthorizeAttribute is working properly when I use it.

Any idea what could prevent the attribute to work and filter accesses ?

Airdrie answered 13/12, 2016 at 13:3 Comment(0)
M
11

Are you inheriting the attribute from System.Web.Http.AuthorizeAttribute? It works differently than System.Web.Mvc.AuthorizeAttribute.

Try inheriting from System.Web.Mvc.AuthorizeAttribute instead.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class AuthorizeRoleOrSuperiorAttribute : System.Web.Mvc.AuthorizeAttribute
{
    private MyAppRole _authorizedRole;

    public AuthorizeRoleOrSuperiorAttribute(MyAppRole authorizedRole)
    { //Breakpoint here
        _authorizedRole = authorizedRole;
    }

    public override void OnAuthorization(AuthorizationContext filterContext)
    { //Breakpoint here
        base.OnAuthorization(filterContext);

        if (!UserInfo.GetUserRoles().Any(r => (int)r >= (int)_authorizedRole))
            throw new UnauthorizedAccessException(ErrorsModule.RoleMissing);
    }
}

That should at least make you hit the breakpoint.

Note parameter difference in: OnAuthorization(AuthorizationContext filterContext) and public override void OnAuthorization(HttpActionContext actionContext)

You can also set filterContext.Result = new HttpUnauthorizedResult(); to get the correct 401 http status code.

Marla answered 13/12, 2016 at 14:13 Comment(1)
Thanks, that was exactly what I was looking for and everything now works as intended. From now on, I'll remember to pay attention to the namespace of my inherited class...Airdrie

© 2022 - 2024 — McMap. All rights reserved.