Authorize Attribute with Multiple Roles

Christian Sauer picture Christian Sauer · Jun 12, 2014 · Viewed 82.7k times · Source

I would like to add Authorization to a controller, for multiple Roles at once.

Normally that would look like this:

[Authorize(Roles = "RoleA,RoleB,RoleC")]
public async Task<ActionResult> Index()
{
}

But I have stored my Roles in consts, since they might change or be extended at some point.

public const RoleA = "RoleA";
public const RoleB = "RoleB";
public const RoleC = "RoleC";

I cannot do this, since the string must be known at compile time:

[Authorize(Roles = string.join(",",RoleA,RoleB,RoleC)]
public async Task<ActionResult> Index()
{
}

Is there a way to circumvent the problem?

I COULD write a const which simply contains "RoleA,RoleB,RoleC" - but I dislike magic strings and this is a magic string. Changing the name of a Role and forgetting to change the combined string would be a disaster.

I am using MVC5. ASP.NET Identity and the Role are known at compile time.

Answer

MacGyver picture MacGyver · Jun 12, 2014

Try to create custom authorize attribute like this.

public class AuthorizeRolesAttribute : AuthorizeAttribute
{
    public AuthorizeRolesAttribute(params string[] roles) : base()
    {
        Roles = string.Join(",", roles);
    }
}

Assuming your roles will be the same for multiple controllers, create a helper class:

public static class Role
{
    public const string Administrator = "Administrator";
    public const string Assistant = "Assistant";
}

Then use it like so:

public class MyController : Controller
{
    [AuthorizeRoles(Role.Administrator, Role.Assistant)]
    public ActionResult AdminOrAssistant()
    {                       
        return View();
    }
}