When discussing authorization in enterprise applications, and particularly when using the .NET framework, the most common answer is to look towards ASP.NET role providers. In many instances this is a fair implementation when it fits in with your application requirements. However, in a lot of cases this just isn't good enough when you need a more granular solution, particularly when permissions come into play with associated roles.
Recently we started to plan a complete rewrite for our flagship product. Given the chance to take a step back and think of our platform outside the bounds of legacy limitations, both in database schema and application architecture, was a great exercise. In doing so we realised that central to our application was the concept of roles (what the business calls persona's) and more importantly permissions.
The requirements that we came up with were:
- Permissions must be associated with both roles AND users.
- Operations must not be static i.e. no enums that pertain to CRUD operations.
- The permissions must span:
- Page Level Access
- Object and Method Level Access
- Feature Level Access
- Must be easy to develop with, whereby a developer would not forget to implement.
Ultimately we require a web based UI whereby internal support staff can configure the roles and permissions on both a group and user basis, giving them granular control of all permissions. The following screenshot shows the ideal solution. In this case using a custom ASP.NET wizard control (a blog post to come) and jQuery iPhone-like checkboxes:
In planning the architecture for the rewrite we considered (briefly) using CSLA.NET. CSLA implements authorization on a granular level down to property level access. In essence however this is still role-based authorization rather than permission-based authorization as ultimately Rocky suggests granting permissions by checking the IsInRole() method on the custom IIdentity object as follows:
public static bool CanAddObject()
The authorization is then performed in factory methods.
public static Project NewProject()
throw new SecurityException(
"User not authorized to add a project");
Another limiting factor in the CSLA.NET implementation is that if you require permissions at a service layer rather than a domain layer then it requires you to write your own implementation on top of the existing CSLA.NET framework, which is far too fragmented a solution.
Eventually I came across an authorization security framework by Ayende called Rhino Security. The great thing about this solution is that it is completely extendible and can integrate in with most domain models (atleast it did for us). Rhino security is an authorization framework that is open to interpretation and implementation and this is why it is such a great solution. A one-size fits all solution is never going to work for an authorization framework as authorization itself is open to interpretation and is likely to be different across all enterprise software solutions.
I'm not going to go into great detail with Rhino Security, because that isn't what this post is about and also mainly because Ayende does such a great job in doing so here, here and here.
The following posts in this blog post series will go into detail as to how to integrate Rhino security into your ASP.NET application, including:
- How to implement dynamic permissions discovery and automatic persistence
- Page level security access using a httpmodule
- Feature and object level authorization
- Creating the administration UI to control permissions