Monday, January 04, 2010 11:08 AM srkirkland

Authorizing Access via Attributes in ASP.NET MVC Without Magic Strings

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!

Filed under: , , , ,

Comments

# re: Authorizing Access via Attributes in ASP.NET MVC Without Magic Strings

Monday, January 04, 2010 3:03 PM by paul.vencill

Makes sense, especially if you want other things to change based on role (e.g. theme).  

For the simpler cases, though, why not just use const's instead of static readonly strings?

# Twitter Trackbacks for Authorizing Access via Attributes in ASP.NET MVC Without Magic Strings - Scott's Blog [asp.net] on Topsy.com

Pingback from  Twitter Trackbacks for                 Authorizing Access via Attributes in ASP.NET MVC Without Magic Strings - Scott's Blog         [asp.net]        on Topsy.com

# re: Authorizing Access via Attributes in ASP.NET MVC Without Magic Strings

Tuesday, January 05, 2010 1:08 AM by Eric

Even though it is a simple implementation it seems that it could get ugly pretty quick. Having to create an attribute for every combination of roles you want to authorize seems like a lot of extra work. I think a better solution would be having a role lookup based on the calling controller, action, and method.

# re: Authorizing Access via Attributes in ASP.NET MVC Without Magic Strings

Tuesday, January 05, 2010 1:10 AM by Kannan

Good information you shared with us. Thanks Scott. You are rocking...

# re: Authorizing Access via Attributes in ASP.NET MVC Without Magic Strings

Tuesday, January 05, 2010 1:54 AM by Shravan Kumar

Good Article.

# re: Authorizing Access via Attributes in ASP.NET MVC Without Magic Strings

Tuesday, January 05, 2010 2:01 AM by srkirkland

@Eric,  This is probably a stylistic decision and would definitely depend on the number of roles/role groups in your system.  I feel that erring on the side of being more expressive with custom attributes for each role is very readable and manageable as long as there aren't an overabundance of them.

# re: Authorizing Access via Attributes in ASP.NET MVC Without Magic Strings

Tuesday, January 05, 2010 2:53 AM by ooswald

nice one.

can we block access completely in a base controller, then whitelist who's allowed using AuthorizeAttributes? feels safer that way.

# re: Authorizing Access via Attributes in ASP.NET MVC Without Magic Strings

Tuesday, January 05, 2010 5:16 AM by Troels Thomsen

If your role names are constant, better make the `const` rather than `static readonly`. This will also allow you to use them as constant expressions.

# re: Authorizing Access via Attributes in ASP.NET MVC Without Magic Strings

Tuesday, January 05, 2010 2:47 PM by Jarrett

I do much the same thing, except I use an enum with the [Flags] attribute. When a user logs in, I build the value and save it in session. Then I can just use

[CustomAuthorize(Roles = Roles.Manager|Roles.ProjectLeader)]

@ooswald, yes, attributes placed in a base controller, then inherited, will carry through.

[CustomAuthorize(Roles = Roles.Admin)]

public class AdminController : ApplicationController { }

public class UsersController : AdminController

{

  // this controller will also require Admin permission.

}

# re: Authorizing Access via Attributes in ASP.NET MVC Without Magic Strings

Tuesday, January 05, 2010 6:47 PM by srkirkland

@paul.vencill & @Troels Thomsen,

  Good suggestion re: using const instead of static readonly strings.  As soon as I made the RoleNames class static I should have made this change as well, it is a lot cleaner.

So if I use const strings I could do [Authorize(Roles=RoleNames.Admin)].  I still prefer the explicit attribute authorization method mentioned in the post, but I am always glad to have more options!

# ASP.NET MVC Archived Blog Posts, Page 1

Monday, January 11, 2010 11:52 PM by ASP.NET MVC Archived Blog Posts, Page 1

Pingback from  ASP.NET MVC Archived Blog Posts, Page 1

# re: Authorizing Access via Attributes in ASP.NET MVC Without Magic Strings

Thursday, January 21, 2010 7:49 PM by Michael Ceranski

I also build custom attributes for my sites. I also tend to build extension methods for toggling the visibility of links and controls on my view pages.

I absolutely hate "magic strings" and I probably go a little overboard trying to make sure that I don't use any in my code.

I wrote a post about Custom attributes and Extension methods on my blog: www.codecapers.com/.../Using-Custom-Security-Attributes-in-ASPNET-MVC.aspx

# re: Authorizing Access via Attributes in ASP.NET MVC Without Magic Strings

Monday, January 25, 2010 6:48 PM by Viet

good work scott.

# re: Authorizing Access via Attributes in ASP.NET MVC Without Magic Strings

Sunday, June 13, 2010 6:32 AM by kikus

отличный пост, автор пиши ещё

# re: Authorizing Access via Attributes in ASP.NET MVC Without Magic Strings

Monday, August 30, 2010 2:04 PM by kitchen

This post reminds me about the old days of good blogging. If you can please visit my site <a href=kitchencheap.co.uk/>kitchen cheap</a>

# re: Authorizing Access via Attributes in ASP.NET MVC Without Magic Strings

Tuesday, September 14, 2010 4:13 AM by shortrun printing

I also build custom attributes for my sites. I also tend to build extension methods for toggling the visibility of links and controls on my view pages.

# re: Authorizing Access via Attributes in ASP.NET MVC Without Magic Strings

Tuesday, September 14, 2010 5:21 PM by stuart clark

nice thanks

# re: Authorizing Access via Attributes in ASP.NET MVC Without Magic Strings

Thursday, October 28, 2010 6:37 PM by Jason Wingfield

Nice work, I like the fact that defining custom attributes abstracts which roles are included. You can easily add or remove roles without touching any of the controller or page code.

Also, taking this one step further you could register roles for each attribute in the database to make updates on the fly without touching any code.

# re: Authorizing Access via Attributes in ASP.NET MVC Without Magic Strings

Tuesday, November 02, 2010 5:08 PM by Dennis

Static Readonly vs Constants

For this implementation, a static readonly field is more desirable than a constant as their values could change in the future.  If you do something like this:

public static readonly string Administrator = ConfigurationManager.AppSettings["key"];

then the constant is useless since it's fetched at runtime from your config file.

On that note, these should really be static readonly properties with just a getter, so:

public static string Adminstrator { get { return "Administrator"; } }

This will hide any implementation should you choose to have a backer field with a private setter.

stackoverflow.com/.../c-static-readonly-vs-const

Other than that, this is a great way to control access on an MVC website =)

# re: Authorizing Access via Attributes in ASP.NET MVC Without Magic Strings

Monday, March 21, 2011 6:53 AM by generalshiva

Does anybody have suggestion if I have two domains where one trusts other and one doesn't trust other.

Leave a Comment

(required) 
(required) 
(optional)
(required)