C# – Custom MVC AuthorizeAttribute that allows for multiple role membership

asp.net-mvcasp.net-mvc-4c++

I've got a custom AuthorizeAttribute class created to handle granular authorization in my MVC4 app.

This is the class:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class isAuthorized : AuthorizeAttribute
{
    public oRoles enRole;

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var authorized = base.AuthorizeCore(httpContext);
        string test = enRole.ToString();
        if (!authorized)
        {
            // The user is not authenticated
            return false;
        }

        var user = httpContext.User;

        bool bFlag = AuthCheck.CheckUser(httpContext, enRole);
        if (bFlag) // I know this is a lot of code; it's for debugging purposes
            return true;

        return false;
    }
}

I've got the following enum declared to allow code helping:

public enum oRoles
{
    StudentSelfPassword = 1,
    StaffSelfPassword = 2,
    StudentLookup = 3,
    StudentChangeRequest = 4,
    StudentAdmin = 5,
    StaffLookup = 6,
    StaffChangeRequest = 7,
    StaffAdmin = 8,
    ChangeQueueApproval = 9
}

In my controller I call the AuthorizeAttribute by:

    [isAuthorized(enRole = oRoles.StudentLookup)]
    [isAuthorized(enRole = oRoles.StaffLookup)]
    [isAuthorized(enRole = oRoles.StudentChangeRequest)]
    [isAuthorized(enRole = oRoles.StaffChangeRequest)]

When I run it through the debugger, The first isAuthorized runs and returns true (as it should) and continues to the second isAuthorized where it returns false then immediately asks me to authenticate. I was expecting it to allow because the first condition was true. However, it appears my assumption was not right.

Originally, I had Roles = "change,admin" which were groups in the domain and it worked but the groups needed to be dynamic in their assignment and not static. I was able to push multiple items ok there. Is that because it was being sent as a string?

Is there a way to essentially do a isAuthorized(…) || isAuthorized(…) || isAuthorized(…) so that if one condition is true it's validated as ok?

Best Solution

In your attribute, rather than having a property with a single oRole, can you have a list or array of roles. And rather than putting a number of attributes, decorate your method with one attribute but pass it an array of allowed roles.

[isAuthorized(enRoles = new oRoles[]{oRoles.StudentLookup, oRoles.StaffLookup })]

An example of creating an attribute that takes multiple values is here

Then in your authorization checking code you can check against all the allowed list that has been provided. Something like the code below

 bool bFlag = enRoles.ToList().Any( r => AuthCheck.CheckUser(httpContext, r));