I work for a community college as their webmaster/web programmer and things tend to be very disparate with regards to systems. The student information system speaks its own language and interfaces with its own data. The Active Directory trees are updated manually each semester. The website has several internal and external tools that various users can use to achieve certain goals.

When trying to communicate across these and other involved systems, it can get a bit crazy. The Web tools are my primary concern. They require authorization granularity that just is not offered via our Active Directory (AD) layout. For example, some of those tools have some users that share a similar AD group and other users that do not. In addition, not all users of an existing group should have access to a given tool. Yet specific collections of users needs access to these tools and I am responsible for granting such access.

An Obvious Solution

The first solution that one may consider is to create new AD groups for the user of the tools. However, the network administrator need not be concerned with these specialized “Web groups” for his routine tasks. He also should not have to worry about granting me permission to create the groups that I continually need, or repeatedly filling requests to create them on my behalf.

When performing audits of the AD entities, the network administrator will have no idea what purpose certain groups fulfill and whether or not they are no longer needed. That is, of course, without constant communication and documentation from me. Likewise, when I absolutely need to add a user to one of the specialized groups in order to grant access to a tool, I cannot be guaranteed quick processing of my request; especially around lunchtime.

A Hybrid Solution

This is where the power of ASP.NET’s custom providers comes into play. To solve the above problems, I devised a hybrid role provider. The new custom provider allows me to see what AD groups a user belongs to and manage my own roles for the website.

I only care about a small subset of all the AD groups, so I mapped them to roles in my database. These mapped roles are not editable via the provider. Therefore, users cannot be added to, or removed from, them since they are virtually a link to the read-only AD groups. I am free, however, to create my own roles in the database and add/remove users to them internally.

The custom role provider handles everything for me. It overrides most of the virtual properties and methods of the base RoleProvider class. It ensures that the provider is not used to modify the AD mapped roles. It also looks up what AD groups a given user belongs to, as well as what users belong to a given group, via LDAP.

Lastly, the custom role provider manages “calculated roles”. Calculated roles are those that are implicit to a user in the website database. These include: instructors, department heads, course coordinators, etc. The presence of one or more records in various tables or the value of a field in a table are ways the calculated roles are determined.

To assist with several aspects of the website’s needs, I also created a custom membership provider that descends from the ActiveDirectoryMembershipProvider class. The main reason for this is to make use of a custom ActiveDirectoryMembershipUser class that contains often needed information about the currently logged in network user.

The Result

With my new custom role provider (and matching membership provider) I get seamless authentication with our Active Directory structure and a very robust hybrid system for authorization. I can create website-specific roles, assign users to those roles, and check users against common AD groups used across the college. Each of these abilities grants me the ease of using the many declarative authorization approaches available to me via ASP.NET. I can configure directories and/or individual pages to authorize users based on their AD group and/or their custom website role.

When completed, I was able to offer the internal users of the website an array of custom tools that are authorized transparently to appropriate individuals. That is some great power allowed by the provider system
in ASP.NET. It was fairly easy to pull off too. I thought out my needs, and with less than a thousand lines of code, I have a complete and robust solution.

The Lesson

Do not accept the lack of a feature as a limitation; especially with regards to the .NET Framework. Sure, there will be times where you are limited (those horrible choices some Framework developers make to mark a very useful method as internal), but with each new version, we (the developers) are given ways to replace entire systems at work across one or more applications.

Happy coding!