Page.User Population From Custom Authenticators For ASP.NET

One of my readers have asked me how to create a custom authenticator for ASP.NET and populate Page.User accordingly. Basically, the scenario is that they have a third-party service that performs authentication and returns the user's identity and other personal data as HTTP headers to the ASP.NET application. The question is, then, how can you populate Page.User with the correct identity as easily as possible?

Before I answer this question, as a consultant I feel obliged to point out that instead of rolling your own identity and access management implementation, you should seriously consider using federated identity as formalized by WS-Federation and implemented by ADFS (and other tools/frameworks).

Anyhow, to answer the question on populating Page.User, assume that an ASP.NET page has a Label control called userLabel_, and you wish to populate it like this:

 this.userLabel_.Text = this.Page.User.Identity.Name;

Basically, you need to pull the user information out of the request and populate Page.User, and while you could do that on every page, a centralized piece of code is to be preferred. An easy way to do this is to write a custom HTTP module.

To create an HTTP module, you must implement the IHttpModule interface:

 public class ThirdPartyProtectionModule : IHttpModule
    public void Dispose()
        // Standard Dispose pattern implementation here...
    public void Init(HttpApplication context)
        context.AuthenticateRequest += this.OnAuthenticateRequest;

The Init implementation is where we subscribe to any events that we wish to handle. In this particular case, we are interested in handling the authentication event. When an ASP.NET application is configured with this HTTP module, the OnAuthenticateRequest method will be executed for each request:

 private void OnAuthenticateRequest(object sender, EventArgs e)
     HttpApplication httpApp = (HttpApplication)sender;
     string userName = httpApp.Request["UserName"];
     httpApp.Context.User = 
         new GenericPrincipal(new GenericIdentity(userName), new string[0]);

Here, we simply extract the user data from the request and use it to create a new IPrincipal instance and attach it to the HTTP context. This causes the Page.User property to be populated with the appropriate data.

Configuring the HTTP module in web.config requires disabling the built-in authentication mechanisms and adding the module:

 <authentication mode="None" />
   <add name="ThirdPartyProtectionModule"
        type="Ploeh.Samples.ThirdPartyAuthenticator.Site.ThirdPartyProtectionModule, Ploeh.Samples.ThirdPartyAuthenticator.Site" />

The custom HTTP module can be a simple class in the web project in question, but it can also be factored out to a separate general-purpose assembly.