Windows Impersonation in C#

Every now and then an application component needs to impersonate another Windows user. Running a chunk of .NET code under a specific Windows account requires calls to some unmanaged functions. It makes sense to wrap this functionality in a separate class or in extension methods. I went for a wrapper class with Impersonate and Revert methods. This is how you use it:

    // Get Current Identity
    Console.WriteLine(WindowsIdentity.GetCurrent().Name); // --> Your current Account
    // Create Impersonation Object
    Impersonation impersonation = new Impersonation("YourDomain", "Test123", "Test123");
    // Start Impersonation
    Console.WriteLine(WindowsIdentity.GetCurrent().Name); // --> Test123
    // Stop Impersonation
    Console.WriteLine(WindowsIdentity.GetCurrent().Name); // --> Your current Account again

And here's the whole class definition:

// <copyright file="Impersonation.cs" company="DockOfTheBay">
// </copyright>
// <summary>Defines the Impersonation class.</summary>
namespace DockOfTheBay
    using System;
    using System.Runtime.InteropServices;
    using System.Security.Permissions;
    using System.Security.Principal;
    /// <summary>
    /// Facilitates impersonation of a Windows User.
    /// </summary>
    public class Impersonation
        /// <summary>
        /// Windows Token.
        /// </summary>
        private IntPtr tokenHandle = new IntPtr(0);
        /// <summary>
        /// The impersonated User.
        /// </summary>
        private WindowsImpersonationContext impersonatedUser;
        /// <summary>
        /// Initializes a new instance of the Impersonation class.
        /// </summary>
        /// <param name="domainName">Domain name of the impersonated user.</param>
        /// <param name="userName">Name of the impersonated user.</param>
        /// <param name="password">Password of the impersonated user.</param>
        /// <remarks>
        /// Uses the unmanaged LogonUser function to get the user token for
        /// the specified user, domain, and password.
        /// </remarks>
        public Impersonation(string domainName, string userName, string password)
            // Use the standard logon provider.
            const int LOGON32_PROVIDER_DEFAULT = 0;
            // Create a primary token.
            const int LOGON32_LOGON_INTERACTIVE = 2;
            this.tokenHandle = IntPtr.Zero;
            // Call LogonUser to obtain a handle to an access token.
            bool returnValue = LogonUser(
                                ref this.tokenHandle);
            if (false == returnValue)
                // Something went wrong.
                int ret = Marshal.GetLastWin32Error();
                throw new System.ComponentModel.Win32Exception(ret);
        /// <summary>
        /// Starts the impersonation.
        /// </summary>
        public void Impersonate()
            // Create Identity.
            WindowsIdentity newId = new WindowsIdentity(this.tokenHandle);
            // Start impersonating.
            this.impersonatedUser = newId.Impersonate();
        /// <summary>
        /// Stops the impersonation and releases security token.
        /// </summary>
        public void Revert()
            // Stop impersonating.
            if (this.impersonatedUser != null)
            // Release the token.
            if (this.tokenHandle != IntPtr.Zero)
        [DllImport("advapi32.dll", SetLastError = true)]
        private static extern bool LogonUser(
                string lpszUsername,
                string lpszDomain,
                string lpszPassword,
                int dwLogonType,
                int dwLogonProvider,
                ref IntPtr phToken);
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private static extern bool CloseHandle(IntPtr handle);


  1. thanks... easy to go through

  2. I tryiend it but i had this error:

    Either a required impersonation level was not provided, or the provided impersonation level is invalid.