I'm currently researching methods for storing user roles and permissions for .NET based projects. Some of these projects are web based, some are not. I'm currently struggling to find the best method to achieve what I'm looking for in a consistent, portable way across project types.
Where I'm at, we're looking to leverage Active Directory as our single point of contact for basic user information. Because of this, we're looking to not have to maintain a custom database for each application's users since they are already stored in Active Directory and actively maintained there. Additionally, we don't want to write our own security model/code if possible and would like to use something pre-existing, like the security application blocks provided by Microsoft.
Some projects require only basic privileges, such as read, write, or no access. Other projects require more complex permissions. Users of those applications might be granted access to some areas, but not others, and their permissions can change across each area. An administration section of the app would control and define this access, not the AD tools.
Currently, we're using integrated Windows Authentication to perform authentication on our intranet. This works well for finding out basic user information, and I've seen that ASP.NET can be extended to provide an Active Directory roles provider, so I can find out any security groups a user belongs to. But, what seems like the downfall of this method to me is that everything is stored in Active Directory, which could lead to a mess to maintain if things grow too big.
Along this same line, I've also heard of Active Directory Lightweight Directory Services, which seems like it could extend our schema and add only application specific attributes and groups. Problem is, I can't find anything on how this would be done or how this works. There are MSDN articles that describe how to talk to this instance and how to create a new instance, but nothing ever seems to answer my question.
My question is: Based on your experience, am I going down the right track? Is what I'm looking to do possible using just Active Directory, or do other tools have to be used?
Other methods I've looked into:
- Using multiple web.config files [stackoverflow]
- Creating a custom security model and database to manage users across applications
Best Answer
Using AD for your authentication is a great idea, since you need to add everyone there anyway, and for intranet users there's no need for an extra login.
You're correct that ASP.NET allows you to use a Provider which will allow you to authenticate against AD, although there's nothing included to give you group membership support (although it's quite trivial to implement if you want to, I can provide a sample).
The real issue here is if you want to use AD groups to define permissions within each app, yes?
If so then you do have the option of creating your own RoleProvider for ASP.NET that can also be used by WinForms and WPF apps via ApplicationServices. This RoleProvider could link the ID of the user in AD to groups/roles per app which you can store in your own custom database, which also allows each app to allow administration of these roles without requiring these admins to have extra privileges in AD.
If you want you can also have an override and combine app roles with AD groups, so if they're in some global "Admin" group in AD they get full permission in the App regardless of App role membership. Conversely if they have either a group or property in AD to say they've been fired you could ignore all App role membership and restrict all access (since HR probably wouldn't remove them from each and every app, assuming they even know about them all!).
Sample code added as requested:
NOTE: based on this original work http://www.codeproject.com/Articles/28546/Active-Directory-Roles-Provider
For your ActiveDirectoryMembershipProvider you only need to implement the ValidateUser method, although you could implement more if you desired, the new AccountManagement namespace makes this trivial:
For your role provider it's a little bit more work, there's some key issues we discovered while searching google such as groups you want to exclude, users you want to exclude etc.
It's probably worth a full blog post, but this should help you get started, it's caching lookups in Session variables, just as a sample of how you could improve performance (since a full Cache sample would be too long).
A sample config sub-section entry for this would be as follows:
Whew, that's a lot of code!
PS: Core parts of the Role Provider above are based on another person's work, I don't have the link handy but we found it via Google, so partial credit to that person for the original. We modified it heavily to use LINQ and to get rid of the need for a database for caching.