Temporary impersonation in ASP.NET

In ASP.NET scenarios it is sometimes necessary to perform impersonation of the (un)authenticated user that makes the request of a resource. This can be done easily from your web.config:

<identity impersonate=”true” />
<authentication mode=”Windows” />

This will cause ASP.NET to run the code for the request under the Windows identity of the requesting user. If the user has not been authenticated, the identity will be that of the anonymous web user account IUSR_machinename.

Using this option inside your web.config is all or nothing: either you are being impersonated for all requests or not at all. But you might want to do a temporary impersonation; just long enough for the access of a business object or SQL Server connection (not preferably from your presentation layer, though) for example.

The System.Security.Principals.WindowsIdentity class has a static method Impersonate for these situations. All you need to do is call this method and receive the return value of type WindowsImpersonationContext. You will hold onto this context while you perform your code under the impersonated account. After you are done with this, you can simply call the Undo on the context object. This will revert the identity to the original one, i.e.before the impersonation started.

Really easy, right? Well, the catch is that you need to have the user token for the Windows account that needs to be impersonated to provide it to the Impersonate method. You could retrieve this using a P/Invoke call to the Win32 API LogonUser, as you would in non-ASP.NET scenarios. But here, we have been authenticated by IIS already. So why bother? You should be able to get the user token in another way, not? And there is. The key is the HttpWorkerRequest class. It has a GetUserToken method that returns the token of the authenticated user or the anonymous IUSR account (if unauthenticated).

Here is a partial piece of code that does exactly this. Have fun with it.

using System.Security.Principals;

publicclass Impersonate : System.Web.UI.Page
{
  protected System.Web.UI.WebControls.Label lblWhoAmI;
  protected System.Web.UI.WebControls.Label lblWhoAmINow;

  privatevoid Page_Load(object sender, System.EventArgs e)
  {
    lblWhoAmI.Text = WindowsIdentity.GetCurrent().Name;

    // Get worker request from provider
    IServiceProvider provider = (IServiceProvider)HttpContext.Current;
    HttpWorkerRequest workerRequest = 
       (HttpWorkerRequest)provider.GetService(
typeof(HttpWorkerRequest));
    IntPtr token = workerRequest.GetUserToken();
    WindowsImpersonationContext context =
        WindowsIdentity.Impersonate(token);

    // Do work under different credentials
    // That should be a little more interesting than this, though
    lblWhoAmINow.Text = WindowsIdentity.GetCurrent().Name;

    // Revert to original identity
    context.Undo();
  }
}

This entry was posted in Uncategorized. Bookmark the permalink.

Leave a comment