Recently I developed a strategy which I think works well for authorizing access to user groups (Roles) without using the string names of those groups.

The problem I am trying to avoid is doing something like [Authorize(Roles=”AdminRole”)] on a controller or action since I know the role names can change & one typo can mess everything up.

Role Names

So first of all I usually have a static class which has the names & aliases for all roles in case they change:

public static class RoleNames
{
    public static readonly string Supervisor = "Supervisor";
    public static readonly string Admin = "StateOffice";
    public static readonly string ProjectAdmin = "ProjectAdmin";
    public static readonly string DelegateSupervisor = "Delegate";
}

 

This is pretty standard for me, but unfortunately I can’t just do [Authorize(Roles=RolesNames.Admin)] because attributes requires constant expressions.  So as a solution I came up with the idea of creating a custom attribute which will tightly control access based on specific role criteria.

Creating a Custom Authorize Attribute

When creating the custom authorize attribute I inherit from AuthorizeAttribute since it already contains most of the logic I need.  All I need to do is set the Roles property in the constructor to a comma delimited list of the authorized roles, and the authorize attribute base class will take care of the rest.

For example – to restrict access to just the admin role:  

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AdminOnlyAttribute : AuthorizeAttribute
{
    public AdminOnlyAttribute()
    {
        Roles = RoleNames.Admin;
    }
}

Or if you want to include the project admins as well:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AdminOnlyAttribute : AuthorizeAttribute
{
    public AdminOnlyAttribute()
    {
        var authorizedRoles = new[] {RoleNames.Admin, RoleNames.ProjectAdmin};
 
        Roles = string.Join(",", authorizedRoles);
    }
}

Usage

Then on your controller you restrict access like this

[AdminOnly]
public class AdminController : Controller{}

And it also works on an action

public class AdminController : Controller
{
    [AdminOnly]
    public ActionResult AdminOnlyAction()
    {
        return View();
    }
}

 

Enjoy!