Windows Impersonation for .Net Made Easy

by Mike Chatfield 1. December 2010 20:02

References:

Echis Framework on Source Forge
Echis Framework Wiki
Echis Framework "MSDN" Style Documentation

Introduction

One of the missing pieces to the System.Security.Principal namespace in the .Net Framework is the ability to Impersonate a user by using the user's credentials (e.g. Name, Domain and Password).  Microsoft provided a way to do impersonation provided you have a valid User Token.  The problem is there was no way within the .Net Framework to "log on" a user to get this token.  In order to perform impersonation using credentials a programmer needed to consult his handy Windows API reference and use functions such as LogonUser, DuplicateToken and CloseHandle.

Since my so-called "Echis Framework" is all about getting rid of the need to constantly write and re-write (or copy and paste) such code, I decided it was time to add some much needed classes to the System.Security.Principal namespace.  The classes described below can be downloaded from the Echis Framework page on Source Forge. The class files are located in the Echis.Core project in the .\Security\Principal folder.


ImpersonationCredentials

The System.Security.Principal.ImpersonationCredentials are exactly what the name implies.  Simply put the class is an XmlSerializable class containing properites for UserName, Domain and Password.  I created this class so that the Impersonation Credentials could be stored as part of a config settings section.  I have left encryption and decryption of the password up to the consuming developer.  As an example of this, I have extended the ImpersonationCredentials class in the Echis.Data.DataAccessCredentials class which uses the already defined DecryptionProvider setting in the Echis.Data.Settings class to decrypt the password.

WindowsIdentityImpersonator

The System.Security.WindowsIdentityImpersonator class is the class that performs the impersonation logic.  The class derives from IDisposable and when the Dispose method is called, the impersonation is stopped.  There is also a static method which instantiates a new instance of the class, begins impersonation and then returns the instance of the class; this static method is called BeginImpersonation.  Alternatively you can simply create an instance of the class and use the BeginImpersonation and EndImpersionation instance methods.

NOTE: The enumerations within the class I "stole" from another blog and forgot where.  If you're the original author of these enumeration classes I appologize in advance!

Here is some sample code showing use of the class:

   try
   {
    using (WindowsIdentityImpersonator impersonator =
      WindowsIdentityImpersonator.BeginImpersonation("UserName",
       "Domain", "Password"))
    {
    // Upon entering the using block (when using the
    // WindowsIdentityImpersonator.BeginImpersonation() method)
    // the identity is impersonated using the supplied credentials
     Trace.WriteLine("Impersonated Identity: " +
       WindowsIdentity.GetCurrent().Name);


     /*** Perform action(s) requiring special permissions ***/

    }

    // After leaving the using block, the identity has reverted
    // back to the user's identity.
    Trace.WriteLine("Normal Identity: " +
      WindowsIdentity.GetCurrent().Name);
   }
   catch (ImpersonationException ex)
   {
    // Handle error message.  NOTE that if the exception is
    // thrown while reverting back to the original Windows
    // Identity, it may be best to gracefully shut down
    // the application rather than allow it to continue
    // running under the Impersonated Identity.
    Console.WriteLine(ex.GetExceptionMessage());
   }

ImpersonationException

The System.Security.Principal.ImpersonationException is the only exception which will be thrown from the WindowsIdentityImpersonator class.  This makes it easy to specifically catch any exception related to the Impersonation logic.

Conclusion

Just one more piece of the puzzle, and hopefully (particularly if you are a .Net developer) you find these classes to come in handy in your own code.  Note that I have put them in the System.Security.Principal namespace, so simply dropping these three class files into your own solution should be sufficient if you don't want to use the Echis Framework.  This is the same for all of the classes found in the Echis Framework.  I published this as Public Domain so that developers were free to "rip apart" the Framework and use the components/classes that are most useful to them.

 

Comments

12/1/2010 8:10:45 PM #

trackback

Windows Impersonation for .Net Made Easy

You've been kicked (a good thing) - Trackback from DotNetKicks.com

DotNetKicks.com | Reply

Add comment


(Will show your Gravatar icon)
  Country flag

biuquote
  • Comment
  • Preview
Loading



Page List