Search code examples
asp.net-mvcauthorizationroles

asp.net mvc decorate [Authorize()] with multiple enums


I have a controller and I want two roles to be able to access it. 1-admin OR 2-moderator

I know you can do [Authorize(Roles="admin, moderators")] but I have my roles in an enum. With the enum I can only authorize ONE role. I can't figure out how to authorize two.

I have tried something like [Authorize(Roles=MyEnum.Admin, MyEnum.Moderator)] but that wont compile.

Someone once suggested this:

 [Authorize(Roles=MyEnum.Admin)]
 [Authorize(MyEnum.Moderator)]
 public ActionResult myAction()
 {
 }

but it doesn't work as an OR. I think in this case the user has to be part of BOTH roles. Am I overlooking some syntax? Or is this a case where I have to roll my own custom authorization?


Solution

  • Try using the bit OR operator like this:

    [Authorize(Roles= MyEnum.Admin | MyEnum.Moderator)]
    public ActionResult myAction()
    {
    }
    

    If that doesn't work, you could just roll your own. I currently just did this on my project. Here's what I did:

    public class AuthWhereRole : AuthorizeAttribute
    {
        /// <summary>
        /// Add the allowed roles to this property.
        /// </summary>
        public UserRole Is;
    
        /// <summary>
        /// Checks to see if the user is authenticated and has the
        /// correct role to access a particular view.
        /// </summary>
        /// <param name="httpContext"></param>
        /// <returns></returns>
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (httpContext == null)
                throw new ArgumentNullException("httpContext");
    
            // Make sure the user is authenticated.
            if (!httpContext.User.Identity.IsAuthenticated)
                return false;
    
            UserRole role = someUser.Role; // Load the user's role here
    
            // Perform a bitwise operation to see if the user's role
            // is in the passed in role values.
            if (Is != 0 && ((Is & role) != role))
                return false;
    
            return true;
        }
    }
    
    // Example Use
    [AuthWhereRole(Is=MyEnum.Admin|MyEnum.Newbie)]
    public ActionResult Test() {}
    

    Also, make sure to add a flags attribute to your enum and make sure they are all valued from 1 and up. Like this:

    [Flags]
    public enum Roles
    {
        Admin = 1,
        Moderator = 1 << 1,
        Newbie = 1 << 2
        etc...
    }
    

    The left bit shifting gives the values 1, 2, 4, 8, 16 and so on.

    Well, I hope this helps a little.