If you’ve developed any moderately complex web application, you’ve probably implemented some form of role-based security. For instance, only administrators can access the /Admin directory. Only ContentCreators can update web page content. Only RegisteredUsers can access the site. ASP.NET makes all of this relatively easy through the <authorization> section of the web.config file(s), programmatic security, and security trimming of site maps. Managing roles is even easier with ASP.NET 2.0 as we now have the role manager (represented by System.Web.Security.Roles) and various RoleProviders. If you’re using the SqlRoleProvider, you can test different configurations of your website by adding and removing your user from various roles and not caching role memberships in cookies. (If you cache your role memberships in cookies, you either have to wait for the cookie to expire or clear your browser cookies every time you change your role membership to ensure that you have the correct memberships.) It’s tedious, but it can be done. Even more tedious is testing role-based security for an intranet application if you’re using Windows groups via the WindowsTokenRoleProvider. Basically your Windows group memberships become your roles. Simple enough – add your user to the appropriate local or domain groups using the Local Users and Groups or Active Directory MMC snap-in and you’re good to go. Right? Not quite. Your group memberships in your user token don’t get updated until you log out and back in again. (I’m ignoring some advanced security APIs that allow you to invalidate your user token and re-acquire it.) Now this is really tedious and is likely going to result in you doing less testing under different role memberships than you really should. Is there a way that we can improve this? I’m glad you asked. Enter the ImpostorHttpModule.
The ImpostorHttpModule is an ASP.NET HttpModule that re-writes an authenticated user’s roles based on a XML file, ~/App_Data/Impostors.xml. To use the module, simply drop the assembly into ~/Bin/ and add the following section to your web.config file:
<add name=”ImpostorHttpModule” type=”JamesKovacs.Web.HttpModules.ImpostorHttpModule, JamesKovacs.Web.HttpModules”/>
Then create a XML file called ~/App_Data/Impostors.xml, which looks like this:
<?xml version=”1.0″ encoding=”utf-8″ ?>
<impostor name=”DOMAIN\Jane” roles=”User, Manager, Administrator”/>
<impostor name=”MACHINE\Bob” roles=”User”/>
The file format should be fairly self-explanatory. The name attribute is the log-in name of the user. It can be a local, domain, forms auth, or other user and is not case sensitive. The roles attribute is a comma-separated list of groups or roles to place the user in. The users can be authenticated by Windows, Forms, Passport, or any other authorization mechanism. The ImpostorHttpModule inserts itself after the authentication event and replaces the role membership of the incoming user with a GenericPrincipal if, and only if, the user is found in Impostors.xml. If the user is not found, their existing role memberships remain untouched. Impostors.xml file is located in ~/App_Data because by default, ASP.NET 2.0 doesn’t allow browser access to any files in this directory. It saves you from having to filter out and deny requests for this file yourself. ImpostorHttpModule monitors the Impostors.xml file for changes. So as soon as you update it with new user or role information, subsequent requests will acquire the new roles. You can see the new roles by browsing to ShowContexts.aspx, which was created by Dominick Baier. (You can download full source from his site here.) At the bottom, you’ll see your role memberships listed. Play around with Impostor.xml and see how your memberships change.
I should note that ImpostorHttpModule is only meant for development purposes. It will get very upset (e.g. blow chunks) with a bad Impostors.xml file. If you need a robust role management system, consider using Windows groups or the SqlRoleProvider. ImpostorHttpModule is meant as a quick-n-dirty testing tool. That said, you can download the ImpostorHttpModule with source code from here. In my next installment, I’ll show how to create a security-trimmed sitemap and test it with the ImpostorHttpModule. Also stay tuned for a detailed walkthrough of the source code where I’ll explain in painstaking detail how ImpostorHttpModule actually works.
EDIT: Updated ImpostorHttpModule to use a comma-separated list of roles to match <authorization> in Web.config and sitemaps.