Don’t Do Role-Based Authorization Checks; Do Activity-Based Checks

I’ve built a few dozen security mechanisms in my career. Unfortunately, I kept getting it wrong, hence the need to keep building them. Over the years, though, I learned a number of different ways that a security system can be built. One of my favorite ways to build authorization systems is through the use of role-based security. The idea is fairly simple: you assign users to roles and roles have permissions. That way you have a nice abstraction that people can be assigned to, as a role, so that you don’t have to assign the same 5, 10, or 500 permissions to every user in your system. It’s a great way to handle authorization when your system has more than a handful of permissions and users. Unfortunately, most of the role-based code that I have ever seen, or written, is done wrong.

 

Stop Using Roles For Authorization Checks

When it comes time to check authorization rules, we often see the role being checked. This is especially true in the .NET arena where Microsoft has built several very specific authorization mechanisms into their frameworks that all expect to use the role as the thing being checked. Does this user belong to this role? If so, go ahead, otherwise throw a security exception.

For example, look at the MSDN documentation for ASP.NET MVC’s AuthorizeAttribute. In the remarks, it states (emphasis mine):

The Authorize attribute lets you indicate that authorization is restricted to predefined roles or to individual users.  This gives you a high degree of control over who is authorized to view any page on the site.

Now .NET is not the only place where this is common, it’s just the place that I have the most experience so it’s where I have found it more often than not. It’s also unfortunate that Microsoft is directly pushing this form of authorization, as it leads a lot of developers (myself included, in the past) to believe that this is how authorization should be done.

No matter what language and what platform / run time you are using, though, you need to stop doing role-based authorization checks. That is not how role-based security should be done.

 

What’s Wrong With Role-Based Authorization Checks?

Plenty of authorization systems have been created with role-based checks, so what’s wrong with them? A lot of things, including documentation and coupling, modeling and encapsulation issues, and requirements growth and change.

 

Documentation

It can be very difficult to know which roles have which permissions in a system. You either create documentation (manually or through code-sniffing tools), or you hope and pray that you can remember everything that a given role is able to do. As a system continues to grow, the problem becomes worse. The documentation has to be updated and you have to hope and pray that the documentation reflects the reality of the executing software.

Having a document that is generated by a tool is a great idea, no doubt. However, it’s only working around the real problem and it doesn’t solve all of the problems, either. Even with a generated document, there is no way to know with 100% certainty that the document you are reading reflects the actual software because the document is not executable. Even if you provide an executable specification (a unit test, or functional test, or some other automated test suite) to cover roles and permissions, there’s no guarantee that a developer didn’t go and add a permission somewhere to fix a bug, with no automated test to back it up.

 

Requirements Growth And Change

How many times have you built a system that has a hard and fast number of roles, throughout the entire lifetime of the system? I can count that on my left hand with half of my fingers missing. Yes, it does happen, but not often in my experience. The typical scenario that I see is a client who says that there is a limited number of roles that they need. With that in mind, we start down the path of using roles as the authorization check and all is well. We know how this story ends, though. Eventually the client will realized that they forgot about a role, or see that what they originally needed is no longer valid and need to change things around to match the actual system.

Look at a portion of the example provided in the AuthorizeAttribute’s documentation, for the use of the attribute:

[HandleError]
 public class HomeController : Controller
 {
     [Authorize(Roles = "Admin, Super User")]
     public ActionResult AdministratorsOnly()
     {
         return View();
     }
 }

 

In this example, we can see the roles that are required being passed into the constructor of the Authorize attribute. This is possibly the worst coupling you can do between roles and authorization. Since attributes in .NET are serialized into the assembly directly, any data passed into the attribute via a constructor must be assembly-serializable. With simple strings meeting this criteria and being serialized into the assembly, the knowledge of which roles are allowed to execute the “AdministratorOnly” action are compiled into the assembly. The only possible way to change which roles can execute this method is to change the code and recompile it.

Not ever authentication system that checks against roles will use attributes, of course. That doesn’t mean the problem goes away, though. Look at this example code as one possible way of handling authorization checks without using attributes:

public class SomeClass
{
  public void DoSomething()
  {
    authorizationService.RequireRoles("Admin", "Super User");
    // some code here that only runs if the user is in a specific role
  }
}

 

There are a number of ways that this can be altered and executed, including the use of custom IPrincipal objects.

It could also very easily be written in another language. For example, ruby:

class SomeClass
  def do_something
    authorization.require_roles :admin, :super_user
  end
end

 

Either way, the problem of coupling the authorization to roles and compiling it down into the assembly has only moved at this point. Instead of being assembly-serialized, it’s now being converted to assembly resources or strings in the code, directly. Either way, the information is still stored directly in the assembly and cannot be updated without recompiling the code.

What happens when your client wants you to change which roles can run the DoSomething method or the AdministratorsOnly action? That’s right – you get to change the code and any associated tests, recompile, re-test, and re-deploy… all because the authorization checks are based on roles.

 

Modeling and Encapsulation

If we were following good object oriented design principles, we would want to have proper modeling and encapsulation of our security needs. This includes the assignment of permissions to roles, whether you are hard coding the assignment or loading the permissions from a database.

If we have our roles hard coded all throughout our system in any place that needs to do authorization, we have no encapsulation of the permissions or assignment of permissions. Encapsulation and cohesion tell us that we should keep all of related bits of information and process near each other, in a manner that allows us to stack the bits together in meaningful ways, without having to duplicate anything. By having our roles thrown all around our code, though, we have none of this. The knowledge of authorization is thrown around the app, in disparate areas, unable to be re-arranged and stacked together into anything more meaningful than just the individual authorization rule at the individual location.


Baby Steps: Load The Roles At Run-Time?

If the problem with the previous code is that the roles are still hard coded into the method call of the authorizationService, then we can fix that by passing the roles into the method through another means – namely by loading the roles that are allowed, at run-time. Here’s an example of what may look like, in a very naive implementation.

public class SomeClass
{
  public void DoSomething()
  {
    var roles = roleRepository.GetRoles();
    authorizationService.RequireRoles(roles);
  }
}

Or in ruby:

class SomeClass
  def do_something
    roles = Roles.all
    authorization.require_roles roles
  end
end

 

But there’s a problem here. In this example, all roles are being loaded up at run time for the requirement check. While this may serve some purpose for some requirement, somewhere, it’s not a likely scenario (at least not one that I’ve seen). In the real world, we need to restrict which roles can execute the code in question. So, what we need here is a way to know which roles should be loaded.

 

Authorize Against Activities

Every example that I’ve shown has used authorization to ensure that users are or are not allowed to perform certain activities within the software. In the original example, the [Authorize] attribute is being used to authorize the execution of the AdminitratorsOnly action on a controller. In the other examples, we’re verifying authorization to allow the DoSomething method to be executed. Each of these can be expressed in terms of activities:

  • Authorize current user for AdministratorsOnly activity on Home controller
  • Authorize current user for DoSomething activity on SomeClass

In the end, all software systems that need any type of authorization will be authorizing against activities, even if those activities are only implied in the security system’s mechanics. Even if we’re talking about data level security – to ensure only certain users can see certain data records – we can still express these security needs as activities. The basic activities surrounding data are typically expressed as CRUD: Create, Read, Update, Delete.

  • Authorize current user to Create a record of specified type (add a new record)
  • Authorize current user to Read a specific record or record of specified type (view the record on the screen)
  • Authorize current user to Update a specific record or record of specified type (edit / save the record on the screen)
  • Authorize current user to Delete a specific record or record of specified type

Look at the previous sample code again, this time with the idea of an activity as your focus for the authorization needs:

public class SomeClass
{
  public void DoSomething()
  {
  }
}

And in ruby:

class SomeClass
  def do_something
  end
end

 

What do you you see, in terms of activities, in this code? The DoSomething method should stand out. The method name indicates some action being performed – an activity in the system. If the code we are writing represents an activity that needs authorization, then let the code represent itself that way. Provide a way for this code to say that it is an action that needs authorization. For example, we can take the previous authorization code and modify it only a little, to provide an activity name that allows us to load all of the roles that are authorized for an activity.

public class SomeClass
{
  public void DoSomething()
  {
    var roles = roleRepository.GetRolesForActivity("Do Something");
    authorizationService.RequireRoles(roles);
  }
}

Or in ruby:

class SomeClass
  def do_something
    roles = Roles.for_activity "Do Something"
    authorization.require_roles roles
  end
end

 

At this point, though, the code is going to get redundant when we start using it throughout our system. Since the roles are loaded by the activity and always passed to the authorization service in the same way, we can encapsulate that call with a higher level abstraction. This also gives us the advantage of removing roles from the direct authorization call, further reducing the mental reliance on the idea of a role being the thing we authorize against.

public class SomeClass
{
  public void DoSomething()
  {
    authorizationService.AuthorizeActivity("Do Something");
  }
}

Or in ruby:

class SomeClass
  def do_something
    authorization.authorize_activity "Do Something"
  end
end

 

Behind the scenes, we are still loading the roles that are allowed to execute this activity. However, we have removed the notion of roles from the authorization call, entirely. We have effectively decoupled the activity from the roles that are allowed to execute it, letting the activity represent itself in a manner that is meaningful, to the authorization mechanism. The authorization mechanism becomes the middle man between the activity that needs authorization and the implementation of the authorization and permissions scheme.

 

Solving The Role-Based Authorization Problems

If we approach the problem of authorization not from the perspective of which roles are allowed to do something, but which activities we must be authorized to perform, we can solve the problems of role-based authorization checks.

 

Modeling And Encapsulation

Activities give us a more intuitive abstraction and the ability to grow and change our security system with relative ease. Instead of sprinkling roles all throughout our code, let the code speak for itself and represent itself as an activity that can be performed. Behind the authorization mechanism that I showed, we can then properly model the relationships between roles and permissions.

We have created a natural boundary between the code that needs authorization and the code that implements the authorization scheme. This boundary gives us an easy way to achieve encapsulation through modeling. Whether we are hard coding the assignment of permissions to roles (as is often done with the ‘ability.rb’ file when using CanCan for authorization in Rails) or loading the list of permissions for a given role from a database, the assignment of roles and permissions can happen in a single location. Even if we need to provide different role -> permission assignments depending on the context of the system or code, we can encapsulate those contexts into their own classes and can use tools like IoC containers to provide the correct permissions set at run time.

 

Self-Documenting Code

Instead of having to search through potentially millions of lines of code to find everywhere that a role is checked, provide a single, consolidated location for the role’s permissions. We no longer have to parse an entire code base to learn and document what roles are assigned to what permissions. We can see the assignment easily because we have all of the relevant information in one place.


Growing An Authorization System

And once we have our authorization system based on activities instead of roles, it becomes fairly easy to grow with our systems requirements and change which roles are allowed to do what. We also start to see change happening in our system along better vectors; rather than having to change and redeploy every time a role needs to have a different set of permissions, we can begin to write code that knows what activities are in the system and change the assignment of activity permissions to roles through better mechanisms.

We also get the benefit of not having to build our security system in an all-or-nothing manner. As the needs for security change, the implementation of the security mechanisms can change. The simple API of letting the code represent itself as an activity and having an authorization class that handles the details of executing authorization checks means we are not tightly coupled to a specific implementation. The internals and implementation of the authorization check can be changed as needed without affecting the use of the authorization API. We can change from hard coded role -> assignment permissions to data-driven assignment, and can change from local authorization storage to LDAP, ActiveDirectory or web services calls.

The system can grow and change as needed, roles can be added and removed, permissions can be changed and we don’t have to touch a large number of files to make the change. If we have a data-driven role -> permission assignment, we can add and remove roles and permission assignment without redeploying the system. Even if we are changing the name of an activity and the code associated with it, we have to change very little to make that happen. Rename the method in question, change the activity name where the method is, and then change the assignment of permission for that activity name. The largest number of changes in this case will be the number of roles that are assigned to the permission. Since the permission assignment is all within the same area of the system, though – and probably within the same file if you’re doing hard coded assignments – then you shouldn’t have any issue finding the activity name and changing it.

 

Simplifying Activity-Based Authorization In .NET, With Attributes

Attributes are not the cause of the problem with ASP.NET MVC example that I showed, previously. In fact, attributes may make your life easier. Here is one example of what an attribute based authorization check in .NET might look like if we’re running off the premise of activity-based authorization.

[HandleError]
 public class HomeController : Controller
 {
     [Authorize(Activity = "Administrators Only")]
     public ActionResult AdministratorsOnly()
     {
         return View();
     }
 }

 

Does that look familiar? The only difference between this and the original example from the MSDN documentation is that I’m specifying the activity instead of the roles. Since our AdministratorsOnly method should represent some activity that the system can perform, though, there really isn’t a need to specify the action name at all. We can use run time reflection and conventions to know that the activity that needs authorization is “Administrators Only” and omit the declaration of the activity entirely:

[HandleError]
 public class HomeController : Controller
 {
     [AuthorizeActivity]
     public ActionResult AdministratorsOnly()
     {
         return View();
     }
 }

 

In this case, I provided a custom attribute named AuthorizeActivity, to prevent confusion or mixup with the built in Authorize attribute.

 

Rails And Conventions For Activity-Based Authorization

On the Ruby / Rails side of things, we don’t have anything that equates to .NET’s attributes. However, we don’t need any equivalent. The CanCan system (my personal preference for authorization in Rails) uses conventions and meta-programming to provide authorization of controller actions and resources. For example, a controller that edits user accounts can be secured with very little code:

class AccountsController < ApplicationController
  authorize_resource
end

 

The authorize_resource method plugs in all of the necessary authorization code to ensure the user that is hitting any of the actions on the controller is authorized to execute that action for an Account.

 

Note: “Action” Vs “Activity”

I used to call this action-based security. However, the recent popularity in Model-View-Controller application architectures has overloaded the term “action”. Most people think of actions as controller actions because of this. While a controller action is certainly an action or activity that may have authorization needs, it’s not the only place that authorization may need to be checked. Using the term “activity” instead of action gives a little bit of differentiation and distinction, to hopefully indicate that authorization is not strictly limited to controller actions.

 

P.S.

Role based authorization is more important than ever as I’ve continued down the path of new languages and platforms, like NodeJS. If you want to keep up to date with how I handle security and related concerns, join my mailing list. You’ll get insights and advice not available anywhere else – and believe me, you don’t want to miss out!


Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Derick Bailey

Derick Bailey is an entrepreneur, problem solver (and creator? :P ), software developer, screecaster, writer, blogger, speaker and technology leader in central Texas (north of Austin). He runs SignalLeaf.com - the amazingly awesome podcast audio hosting service that everyone should be using, and WatchMeCode.net where he throws down the JavaScript gauntlets to get you up to speed. He has been a professional software developer since the late 90's, and has been writing code since the late 80's. Find me on twitter: @derickbailey, @mutedsolutions, @backbonejsclass Find me on the web: SignalLeaf, WatchMeCode, Kendo UI blog, MarionetteJS, My Github profile, On Google+.
This entry was posted in .NET, Analysis and Design, AntiPatterns, C#, Model-View-Controller, Rails, Ruby, Security. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Anonymous

    Just so I’m clear.  You’re system still assigns roles to users, but then abstracts what roles can perform a given activity right?

  • http://twitter.com/hotgazpacho Will Green

    For your Ruby apps, have you looked at Ryan Bates’ CanCan? https://github.com/ryanb/cancan

    • http://mutedsolutions.com Derick Bailey

       yeah, dude… mentioned it twice in the post. :) it’s my preference for rails authorization.

  • Anonymous

    Okay, I do something similar by using extension methods off of our user object.  A module would be a good approach in Ruby I’m guessing.

    user.CanDoSomething()

    which abstracts which roles can do what.

    We can access the user from anywhere through the application context.

    I’ve got custom authorization filters for mvc actions
    [RequiresRole.DoSomeAction]

    Should probably rename the attribute, but it has a bunch of nested classes that let me override the  authorization rule.

    • http://mutedsolutions.com Derick Bailey

      Nice – looks very similar to what CanCan provides for rails. It gives us a great set of tools for Rails, including several modules that are tacked on to controllers and views, giving us a handful of methods we can call to authorize things.

      similar to your user.CanDoSomething() call, CanCan let’s us call:

        can? :do_something

      it uses the current_account or current_user (don’t remember which) and the defined CanCan abilities (permissions between user or role, and activity) to check the current user against the role specified. so, for example, we can do this in a view (using HAML)

      - if can? :do_something
        = render :partial => “show_something”

      and if the user has permission to “do_something”, then the view partial _show_something.html.haml will be rendered at that location.

    • http://twitter.com/PostHopeLive Paul Barton

      I have thought about building extension methods off my User.cs entity but it always felt wrong. Am I wrong about this? I ended up with something like Authorize.CurrentUser.CanDoSomething(); and Authorize.CurrentUser.Can(Func action);

  • http://peter.mounce.myopenid.com/ Peter Mounce

    In a previous company I had to code security, and the requirements didn’t even get written down, let alone remain static for more than a few days at a time.  In the face of this, I decided to use Ayende’s Rhino.Security (https://github.com/ayende/rhino-security), which nicely solved the problem because it allowed us to define security rules in data, not hard-codedly.  

    It _also_ forced the product owner to actually think about (and write down!) the operations within the system that needed to be secured, and the actors within the system that performed those operations.  That was actually more important in the longer run than having the ability to react to change easily (which we kinda got for free, of course).

    • http://mutedsolutions.com Derick Bailey

      have to say i’m impressed that you actually got rhino security working! i spent a few weeks trying to get it to work once. painful experience.

      i loved the idea of how he built it, though, and i took some of those ideas and implemented my own versions of it a few times.

      and +1 to actually writing down security needs. though in my experience, even when it’s written down, it changes before the system goes live.

      • Eric

        I agree with this guy and I don’t want to think a lot.

  • Chris Tavares

    In reading this, it looks to me like you’ve just gone back to checking permissions. Is there a difference between a permission and an activity (from the security perspective)?

  • Raif

    Hey Derick,
    I use RhinoSecurity too.  I had to compile it with NH 3.0 but it seems to work pretty well. I mean it took me a while to get it working but I’d say about 95% of that was cuz I’m an idiot.  RS uses embeded hbm files and I use fluentNH ( like a normal human being ) and that threw me a bit but it turned out not to be an issue really.  
    I have not started to use the Entity Group Permissions yet but I hope to wrap my brain around those soon.
    Long story… long, I think RS is worth a look.
    Raif

    • http://mutedsolutions.com Derick Bailey

      good to know that i’m not the only idiot around. :)

      i should also say that i tried RS 2 to 3 years ago. i’m sure it’s come a long way since then.

  • Roe

    Really excellent Derick.

  • Simon Bartlett

    We’re also using Rhino.Security on our project and it works nicely. Unfortunately Ayende no longer maintains it, but that doesn’t stop anyone forking it.

  • http://twitter.com/technoag Alan Baker

    I’ve used AzMan on several projects, and most recently NetSqlAzMan ,http://netsqlazman.codeplex.com . AzMan supports Groups, Roles, Operations, and Tasks.

    • http://mutedsolutions.com Derick Bailey

      I haven’t had a chance to look into AzMan in depth, but I’m aware of it. Looks like NetSqlAzMan does what I’m suggesting, though.  thanks for the link!

      • Anonymous

        I’ve looked into NetSqlAzMan which is a nice project. It allows for the nesting of “roles” essentially which is something that is really missing from the .NET roles system. What it was missing that I feel most systems are missing though is an extra layer that answers the question “Which items does a given role authorize a certain activity on?” For example, using a blog as an example, you have many blog posts, but what if you only want to give a certain user/role permission to “DeleteBlogPost” for certain blog posts?

        I’m currently working on a system (one that I hope to open source someday) that has 3 hierarchies: user/role, item, permission. It allows you to nest permissions and roles (like NetSqlAzMan), and also lets you nest items. Each of the 3 hierarchies have a root node (Everyone, Everything, FullControl). In this scenario, it’s easy to setup an Administrator role that has access to do everything no matter what is added to the system. You simply give the “Administrators” role “FullControl” on “Everything.”

        It’s been quite challenging so far but I think it’s coming along well.

        • http://mutedsolutions.com Derick Bailey

          that’s a great observation… one that i completely missed in my post. when it comes to CRUD (create, read, update, delete) operations on data models, i typically approach that as separate activities that can be taken against models.

          the easiest way for me to illustrate this is with CanCan for rails. with CanCan, i can specify a role’s ability to manage a particular model. In your example blog post, i can assign a user rights to delete the post like this:

            can :delete, BlogPost, :user_id => blog_owner.id

          this rule says: “The blog owner can delete blog posts”

          in this example, “blog_owner” is the user account that owns the blog. BlogPost is the class that represent the blog post. it has an attribute (property) called user_id. to break it down a little, it goes like this: assign delete permissions for blog posts, to the user who’s ID matches the BlogPost.user_id.

          the great thing about CanCan is the ability to specify any arbitrary action that I want, against a model. I can provide all the CRUD operations through the :manage permission, or individually as :create, :read, :update, :delete, or any other permission i want, such as :comment which may be used to determine if the user is allowed to comment on a post.

        • likethesky

          Sorry to resurrect a year-old thread, but YES! I am about to implement a system similar to what @ttutko:disqus describes here, which is that Administrators are able to assign to new users what I call a “sub-admin” role (with that name being a role which is semantically the same or–most probably–*less* than “Administrator”, with a corresponding set of the same or less [data] items [as available to Administrator] and with the same or less permissions on those items–jointly, these last two [items & permissions on them] define an “activity” [as @derickbailey:disqus defines it in the original post here--I think!] that then either can -or- can’t be performed by that [sub-admin] user).

          Then–in my system–this sub-admin user should be able to further sub-assign other sub-admins or sub-users (the only distinction between sub-admins & sub-users being whether they can further assign users; sub-admins can assign *the same or less* rights they have to other users, sub-users cannot–it’s really just another permission that is strictly on the User model/resource). Anyway, I digress…

          Anyone know of any GitHub projects that do something similar (or @ttutko, have you open-sourced any of your system–or do you plan to? Or could share some snippets of code for it)? I’d be most interested in anything done using CanCan/Rolify in Ruby/Rails, but am open to any solutions that implement some form of this nested system, with sub-admins able to further delegate the same or ‘tighter’ permissions for resources (uh, I mean ‘items’) that they have those (or greater) permissions to already.

          One question I have is–let’s say there are a dozen ‘items’ with the four main CRUD actions on them (defining 48 possible activities) and of course we will be adding more ‘items’ to these dozen all the time. Should I just create a ‘custom role’ (hash into the 4 x 12 table of ‘checkmarks’) in Rolify for whatever permissions any particular user is given by a sub-admin (meaning, create a new ‘custom’ role each time some combination of those 48 ‘checkmarks’ are checked by a sub-admin for one of their sub-users/admins–we would share a combination that reoccurs, of course)? Or better to just keep adding the ‘items’ x 4 into a separate table linked to from the User table itself? IOW, not use custom roles at all for these sub-permissions/activity-based authorizations, but simply make that ‘hash of permissions on items’ a part of the identity of that user?

          Thanks all!

          • thinkfarahead

            I link Permissions directly to the user instead of rolling a Custom Role. In fact, the only reason I have roles in my framework is for the users to be able to assign “canned set of permissions” to a user. If the permissions are not customized, I also link the role to the user (just in case, if I ever need to authenticate by role, for example, a hierarchy of administrators).

  • http://www.hire-web-developers.com/ website coder

    we are thinking that that one is very difficult to follow that.. But through this post we can do easily to follow that activity based checks.. Thanks for this great work sharing with us..

  • Mihai Lazar

    I think I use something similar, except I call them Permissions instead of Activities. Orchard has the same concepts.

    Permissions are exposed bt the feature you are currently working on. Permissions are handled by the developer.

    The user can define whatever Users or roles he wants. I assign Permissions to existing roles. And use the Permission within the current feature.

    So the authorization part would look like [Requires(Permissions=Permission.AdministratorsOnly)].

    Good read, thanks.

  • http://truewill.myopenid.com/ Bill Sorensen

    It seems like an (important) semantic question. If you redefine “role” as “activity” and use an implementation that supports adding individuals or groups to other groups (such as Active Directory Services), then you really don’t need to do anything other than be careful with your “role” names. Create an AD group named “Administrators Only” and add Admin and Super User to that. Done, with no code changes.

    • http://mutedsolutions.com Derick Bailey

      I’m not redefining role as activity, actually. I still use roles to manage permissions for users. Every user is assigned to one or more roles. Roles are then assigned permissions. A permission is the ability (or denial of ability) to perform an activity.

      … probably should have made that a little more clear in the post.

      the “Administrators Only” is a terrible example of an activity name, in the post, too. I kept that example because it was based on the examples from the MVC documentation. There’s no action associated with that wording… it does sound more like a role is being specified, but the intent was to show that an activity can be arbitrarily named and used in place of role-based checks in code.

  • Scott Densmore

    Good article. If you get a chance you should look into Claims Based Authorization using WIF (Windows Identity Foundation).  I think your abstractions still work but now you become much more portable and it sees authorizations on activities not roles in the ClaimsPrincipal.

  • Daniel Liuzzi

    Great read, Derick! What you describe sounds a lot like Claim based authorization, from the System.IdentityModel.Claims namespace. You can refer to the following link for a nice walk-through on implementing this in an ASP.NET MVC application:

    Implement custom Claim based Authorization in ASP.NET MVC Web Application – http://geekswithblogs.net/shahed/archive/2010/02/05/137795.aspx

    • Anon12

      Thanks a lot, I was looking for it. Someone have some idea about how to create something like [DoAuth]  and the filter get current user object from session and current activity by reflection in generic way ?

  • PhilM

    Hi,

    Nice post. Rather surprising to learn that authz is done in this manner in the frameworks you mention. FWIW, I worked on a XML gateway a decade ago and implemented an RBAC system. It was built on top of Java’s framework JAAS. I don’t have the code to check but I am pretty sure we stuck to using Privilege everywhere to allow actions (Privilege is what you are calling as Activity — I think). It was quite robust in security that one could even load external jars into our gateway safely as the core code ran in its own sandbox.

    It’s funny (or not!) that Microsoft gets key things wrong time and again despite having prople hired with their much talked about interview process! Perhaps, their engineers should be inspecting round man holes than implement software! 

  • Christian Koenig

    This is what I have been thinking about the last months. Seen it gone wrong in PHP and Play Framework. Began to learn .NET and seen it again.
    I could totally follow you, up to the following point:
    “We can use run time reflection and conventions to know that the activity that needs authorization is “Administrators Only” and omit the declaration of the activity entirely.”
    This is where you lost me… could you point me to the right direction where I can use Reflection within a ActionFilter to omit the Activity declaration?
    greetings
    Christian

    • Christian Koenig

      Got it on my own!
      User Reflection to scan the namespace, in my example the controllers. Store all ActionMethods (in relation to their controller) as Entities. Create associations: ActionMethod Functionality(Activity)  Role Group User.
      Make your custom authorization filter check this information. Thanks! I finally got rid of those code based access restrictions.

      • Shurller

        Can you explain further how you achieve this? Or better still if you can share your sample code.

  • Derrick Becker

    Hey Derick.  Do you know if there is a practical size limit for claims?  We are investigating using claims based authorization in SharePoint and .Net WCF services.  If I store claims in Active Directory as activity level permissions, then a user with many roles that are tied to many permissions could end up with a very large claims token.  Just wondering if you have advice on this and if there is any limitations or size considerations.

  • Warren Sentient

    Thank you for the excellent article.

    • Anonymous

      I share your sentiment here, we realized this problem years ago. Indeed I’m very surprised that you didn’t mention the biggest paing we had with role based security, what about dynamic roles?

      What happens when the client wants to change dynamically roles and assign then different permissions overtime? The whole role based security fails when dynamic roles appear.

      So, in essence we did the same as you, as we allowed dynamic roles to be created, we needed to check some other fixed point, so we decided to check directly for permissions.

      As you did, our permissions represented activities in the systems, so we are doing the same here.

      I still think that the whole role based security is broken, and only works for very simple scenarios that do not change over time. But what scenario does not change over time?

  • rbac_abac

    Modern authorization architecture is based on XACML processing model (where the authorisation system provides distributed, embeddable PDP — policy decision engine).
    That engine must be consulted by the application before the end user gets to access a protected resouce:
    checkAuthorisationAccess(user, activity, target_resource, application-context-attributes) would return allow or deny
    The application must not even be aware of the roles that a user has (storing the roles, and interpreting them is the job of PIP and PDP). PDP engine also implements what’ is caled ABAC (attribute based access control, typically by embedding a light weight rules engine).

  • Spamme

    Nice article, alas you don’t give any sample project from where people can begin, it would be very useful.

  • Manfred Lange

    Derick, I like in particular your approach of thinking in terms of activities as opposed to roles. I gave it a try and it is driving the design of systems in a much better direction. Thank you for sharing!

  • kkkk

    In the end that is what RBAC is all about. http://csrc.nist.gov/rbac/rbac-std-ncits.pdf

  • http://www.facebook.com/profile.php?id=577075530 Chris Nevill

    Excellent article. Would love to see a working solution.

    In my ideal world at the moment I’m looking for something that allows me to have it such that all actions are not authorized until a combination of an activity has been defined for that action, a role has been given access to that activity. A user assigned that role would then be authorized for that activity.

    I’d like control of where the users credentials are stored, so that they can be stored in my database. I’d also like the database to tie the activity’s and the rolls, so that I could simply change the database to change where users with a certain role can and can’t go.

    I’m sure there must be a nice ‘simple’ solution for this somewhere. I’m not feeling confident about rolling my own yet.

  • Jeff Shurts

    Software development is one of those disciplines where there always tend to be a thousand ways to solve a particular problem. Of those thousand, 990 are usually pretty bad, and any of the remaining ten will serve you pretty well.

    Authorization (access to features) in an application, whether it’s a web, desktop, or mobile app, is one of those problems that clearly has one best solution – tackling the problem any other way represents a compromise that you’ll regret somewhere down the road.

    That one best solution is the one Derick describes above. Just do this. If you don’t, you (or those who have to maintain your code after you move on) will be forever frustrated.

    For those of you wanting a more elaborate example, just go watch the Railscast on the CanCan gem (which is referenced above, and incidentally, was authored by Ryan Bates, the man who brings you Railscasts). Even if you’re not a Rails person, you’ll get the concept. It is, after all, quite simple:

    NEVER INQUIRE ABOUT THE CURRENT USER’S ROLE IN APPLICATION CODE. EVER.

    Do not let complex and tedious authorization rules (“who gets to do what?”) become scattered throughout your code base, never again to be understood in their entirety. Because one day a new product owner will ask you for a list of said rules. You don’t want to be scanning your code base looking for calls to User.getRole() or some such. There are far more entertaining ways to waste time.

  • Jason Dang

    I dont agree with the author since the Enterprise Library has Unity block which allows us to inject the Authorization mechanism into the biz classes. That make our security mechanism very clear, loose-couple and easy to add custom roles. Your code seems to be outdated.

  • Rob G

    So, in the end you’re simply saying don’t do role-based security wrong – by checking roles directly rather than checking that a role has a particular permission.

  • Guest

    *Excellent* !

  • mrns

    Nice article, man..one third of the universe would be much better if people share deep experience plain simple as you’ve done here.

  • Alan Greenblatt

    Very nice article. This is exactly how WordPress authorization works. Django framework does the same thing and also allows you to add specific permissions/activities to individual users because sometimes you don’t want to have to create a whole new role (Group in django-speak) just to give one user a specific permission. But, of course, that can quickly get out of hand.

  • http://ayottesoftware.com/ Richard Ayotte

    This is the best approach that I’ve seen when you can’t do AOP. AOP is still king however for separation of concerns and complete decoupling.

  • MacUndecided

    I think that the article does a great job of documenting why roles based security is a bad idea but the alternative proposed here is equally lacking.

    Ideally a good generalized security model ought to specify what activities may be performed upon a specific object. In other words it must answer “who is allowed to perform some activity upon some entity”. This means that you must be able to associate activities that may be performed to specific objects. For example I may have the update account activity privilege on MY account but I probably ought not to have that same privilege on YOUR account.

    Also, in federated systems, you may want to use a form of attribute based access control, wherein the authentication system, provides the credentials, and then aggregates a set of attributes that get passed along with the credentials to the entity that is performing an authorization check.

    The Authorization entity may want to implement rules such as:

    Allow read on patient.medicalHistory if requestor.isDoctor and requestor.hasPatient(patient).

  • kibria

    Is there any sample project that can I download and see it?

  • disqus_l18zipEHAg

    hello