Role/Group Management

Role/Group Management

Old forum URL: forums.lhotka.net/forums/t/724.aspx


Gigatron posted on Tuesday, July 25, 2006

Anyone have any suggestions on frameworks and/or patterns that can be used to manage user roles/groups?  The examples using csla are very basic at best and only handle roles.  I need something that is configurable and dynamic that can handle groups that can contain roles.  I need to either build or find a framework to handle my needs.  This needs to be intergrated with asp.net forms authentication. 

I'm thinking I need to build a custom role/membership providers and a framework that can assign objects, properties and processes to roles, which can then be assigned groups.  There must be some solutions aready built?  This seems like something that would be common in large scale systems.

SonOfPirate replied on Tuesday, July 25, 2006

I agree.  However, we ended building our own.  A CSLA-style framework does support this well.  all depends on how complex you want to get.  Ours is pretty complex and rivals Windows/ActiveDirectory but integrates tightly with the object-level authorization scheme provided with CSLA (e.g. CanReadProperty, CanWriteProperty, etc.)

If you find something pre-built, post it here.  I'd be very interested in seeing what others have done.

Gigatron replied on Tuesday, July 25, 2006

Yeah, this is what I was fearing, having to build a framework to handle group/role management.  I'm thinking of having roles/groups that are assigned objects and what properties and processes of those objects are allowed/denied/etc.

Ruckus77 replied on Tuesday, July 25, 2006

I'd be very interested in seeing your complex system that is tightly coupled with CSLA. I am working on a similar solution myself.

Gigatron replied on Tuesday, July 25, 2006

I am really mystified why there is no framework available.  It seems to me that Role/Group management is an important part of any system these days.  This will cost me alot of time to build something.

SonOfPirate replied on Tuesday, July 25, 2006

The issue I found is that there are a number of working examples out there but they are usually simplistic at best (only user/role) or don't come anywhere near what we needed.

In a nutshell, we extended our framework to include an entire security model for our applications that includes User and Group classes.  These are both data classes (as are supporting UserCollection, GroupCollection, etc.).  We have a configurable switch that indicates how the application is to handle security:

Our SecurityManager class provides a gateway mechanism for most of the settings and functions such as getting the CurrentUser.

We have incorporated Account Lockout and Password Policies similar to Windows as well.  Just to further complicate things.

Because we have the ability to enforce password history via the policies, we actaully have a Password object and PasswordCollection that handles all of the behaviors and logic associated with a password.

Both User and Group are derived from Actor which enables us to have both User objects and Group objects as members of a Group.

The Group object maintains a list of Roles associated with that Group.  We debated allowing direct assignment of Roles to a User but opted to not implement that - at least not yet.  The master list of roles that can be assigned to a Group is found in resource files embedded in the application.  Because this is not something you want your users tampering with, this seemed like a good way to go.  Plus, it gives us the ability to localize the role descriptions should we be dealing with a multi-lingual app.  The SecurityManager class exposes a Roles property which is a RoleCollection.  The SecurityManager uses config settings to load all of the "user-defined" resource files - in other words, it knows about the resource file embedded in our framework, so we use config 'hooks' to allow additional resource files containing application specific roles to be added to the list.  Oh, the other benefit is that we can refer to the resource name in code when performing authorization checks and not have to worry about how we spelled the role or if a word was capitalized, etc.

Everything is flexible, scalable and inheritable for extensibility.  For instance, our policies are designed to allow additional policies to be defined for the application seamlessly with the built-in ones.  In fact, we can add additional settings to the built-in ones through the config file.

I know that sounds like a lot and it did take us quite a while to develop, but, we were able to (at least in my opinion) take the best of what's out there and come up with a stable yet robust and flexible model to include in our framework.  So far it has worked great.

Outta time on this end, but I'd be more than happy to answer any specific questions that you might have.

Hope that helps.

Gigatron replied on Tuesday, July 25, 2006

How did you handle intergrtaion with CSLA?  Do you have a front end for administrating what Roles can do?  For instance, how do you assign a role read/create/updates to csla objects so no hard coding is involved?  For example:  You have Order object and 2 roles, one with read/create/update and one with read.  How do you do handle this without any hard coding in your Order object?  My systems needs to be dynamic, where the above scenario may change and we have a new role that has only update acces for instance.  I don't want to have to make code changes and recompile.  Recompiling is not an option for me and needs to be dynamic and manageable.

SonOfPirate replied on Tuesday, July 25, 2006

Let me answer the first question...well, first.  The integration with CSLA comes from the fact that our security objects are dervied from the CSLA base classes and make use of the same features and functions provided therein.  For instance, the ability to create new users is an authorization feature just like any other.

A word of correction from my previos post.  I tend to misuse the terminology and it constantly gets me in trouble.  I have been working on getting it straight but still instinctively fall back to the User-Group-Role nomenclature when in reality it is User-Group/Role-Right.  This is the correct terminology in our model and may help to understand things better.  Too many people interchange the term Group and the term Role that they essentially mean the same thing now - hell, even Microsoft does it...IsInRole(...)!  Take a look at the WindowsIdentity and you'll see a Groups property!!!  Even they switch 'em up.

Anyway, what we have is a User that hold membership in 'x' number of Groups each of which can also be thought of as a Role and contain a set of assigned Rights.  An example of a Group, or Role, would be 'Order Entry Clerk' while a Right would be "Can add new orders".  With me?

Now let me try to address the rest all together...

I agree with the need to be flexible and dynamic.  Those were the tenets of our design as well and can be seen in the extensibility provided through config files, inheritance, etc.  However, there is a compromise to this flexibility based on real-world implementation.  That being where the rights are defined.

They have to be defined somewhere.  In our case, all rights are defined in a resource file embedded in the project.  So, we have a resource file embedded in our framework that contains a list of all rights for objects in our framework, such as creating a new user.  When we create an application making use of our framework, we can (obviously this is optional) create a second resource file embedded into the application that will contain the rights for any new objects created for the application.  These rights are then used in conjunction with the AuthorizationRules collection held by each business object.  The concept we used is basically the same as Rocky's except that we've added the extra layer to the model, so the "role" that is used when establishing an AuthorizationRule is one of these values whereas the roles used in the book translate to Groups in our model.

So, for your example, our application would have a resource file with three string resources added:

You would have two Groups/Roles defined:

The first would have all three rights assigned while the second only the ReadOrderRight.

Then, your Order object would use these rights to authorize the user to perform the requested operation.  For instance, in the CanAddOrders static method, you would check to see if the current user has the CreateOrderRight in its list.

FYI - the authorization task in our model is delegated to the SecurityManager object which has a static Authorize() method accepting the right to check against.  So, CanAddOrders would look something like this:

public static System.Boolean CanAddOrders()
{
    return SecurityManager.Authorize(CreateOrdersRight);
}

So, even though you are coding the rights into the objects, assignment of the rights to users (via Groups/Roles) is dynamic and can be done via a user-interface (which we do have both Web and Windows controls for managing our security objects in our framework).

The only other way I can think of to do this that would remove the hard-coded rights from the object would be to use more of a traditional ACL-type approach where the Order object maintains a dynamic list of Users and/or Groups/Roles that are allowed various access rights.  We did look into this and opted for the approach listed above.  Our thoughts here were that all objects have a standard set of rights: Read, Create, Modify and Delete.  When you add an entry into the ACL for an object you define which of these rights are being granted.  Then, your Authorize routine can check the object's ACL for the current user and cross-check to see if the requested right has been granted.  This is similar to how file security works in Windows.  There are some built-in classes that can help with this in the System.Security.AccessControl namespace.

My hope is that we eventually combine these approaches because I like the idea of being able to set priviledges on an object-by-object basis when applicable as well as the more global approach we've already taken.

Hope that answers your questions.

 

Gigatron replied on Wednesday, July 26, 2006

Thanks for the detailed response SonOfPirate.  Thats along the lines of what I will end up implementing, only difference is I will be using aspnet forms authentication.  I plan on storing all my access information in tables though.  This way I can have a front end for configuration.

lefty replied on Tuesday, May 01, 2007

I really like this approach and I think I'm going to try to implement something similar in my project, however I have a question.

What method do you use for linking the rights to the Group?

What I invision is a table with columns (GroupName, Right) and each row specifies a Group/Right combination.  I'm also wondering if the Rights are saved in a resource file in the application, how do you represent them in the Database?  An integer?  Or maybe a string that is defined in the resource file?

Thanks,
Jeff

skaue replied on Wednesday, May 02, 2007

Now where can I download your code, SonOfPirate ;-)

(just kiddin)

Copyright (c) Marimer LLC