ASP.NET MVC3 Role and Permission Management -> With Runtime Permission Assignment

Anthony Gatlin picture Anthony Gatlin · Sep 2, 2011 · Viewed 19.2k times · Source

ASP.NET MVC allows users the ability to assign permissions to functionality (i.e. Actions) at Design Time like so.

[Authorize(Roles = "Administrator,ContentEditor")]
public ActionResult Foo()
{
    return View();
}

To actually check the permission, one might use the following statement in a (Razor) view:

@if (User.IsInRole("ContentEditor"))
{
    <div>This will be visible only to users in the ContentEditor role.</div>
}

The problem with this approach is that all permissions must be set up and assigned as attributes at design time. (Attributes are compiled in with the DLL so I am presently aware of no mechanism to apply attributes (to allow additional permissions) such as [Authorize(Roles = "Administrator,ContentEditor")] at runtime.

In our use case, the client needs to be able to change what users have what permissions after deployment.

For example, the client may wish to allow a user in the ContentEditor role to edit some content of a particular type. Perhaps a user was not allowed to edit lookup table values, but now the client wants to allow this without granting the user all the permissions in the next higher role. Instead, the client simply wants to modify the permissions available to the user's current role.

What options are strategies are available to allow permissions on MVC Controllers/Views/Actions to be defined outside of attributes (as in a database) and evaluated and applied at runtime?

If possible, we would very much like to stick as closely as we can to the ASP.NET Membership and Role Provider functionality so that we can continue to leverage the other benefits it provides.

Thank you in advance for any ideas or insights.

Answer

Darin Dimitrov picture Darin Dimitrov · Sep 2, 2011

What options are strategies are available to allow permissions on MVC Controllers/Views/Actions to be defined outside of attributes (as in a database) and evaluated and applied at runtime?

A custom Authorize attribute is one possibility to achieve this:

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        Roles = ... go ahead and fetch those roles dynamically from wherever they are stored
        return base.AuthorizeCore(httpContext);
    }
}

and then:

[MyAuthorize]
public ActionResult Foo()
{
    return View();
}