WindowsIdentity Impersonation using C# Code

using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Principal;
using System.Runtime.InteropServices;
using System.Security.Permissions;

namespace Test
{
    public class ImpersonateUser
    {
        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool LogonUser(
        String lpszUsername,
        String lpszDomain,
        String lpszPassword,
        int dwLogonType,
        int dwLogonProvider,
        ref IntPtr phToken);
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public extern static bool CloseHandle(IntPtr handle);
        private static IntPtr tokenHandle = new IntPtr(0);
        private static WindowsImpersonationContext impersonatedUser;
        // If you incorporate this code into a DLL, be sure to demand that it
        // runs with FullTrust.
        [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
        public void Impersonate(string domainName, string userName, string password)
        {
            //try
            {
                // Use the unmanaged LogonUser function to get the user token for
                // the specified user, domain, and password.
                const int LOGON32_PROVIDER_DEFAULT = 0;
                // Passing this parameter causes LogonUser to create a primary token.
                const int LOGON32_LOGON_INTERACTIVE = 2;
                tokenHandle = IntPtr.Zero;
                // ---- Step - 1
                // Call LogonUser to obtain a handle to an access token.
                bool returnValue = LogonUser(
                userName,
                domainName,
                password,
                LOGON32_LOGON_INTERACTIVE,
                LOGON32_PROVIDER_DEFAULT,
                ref tokenHandle); // tokenHandle - new security token
                if (false == returnValue)
                {
                    int ret = Marshal.GetLastWin32Error();                   
                    throw new System.ComponentModel.Win32Exception(ret);
                }
                // ---- Step - 2
                WindowsIdentity newId = new WindowsIdentity(tokenHandle);
                // ---- Step - 3
                impersonatedUser = newId.Impersonate();
            }
        }
        // Stops impersonation
        public void Undo()
        {
            impersonatedUser.Undo();
            // Free the tokens.
            if (tokenHandle != IntPtr.Zero)
                CloseHandle(tokenHandle);
        }
    }
}

how to use it

             ImpersonateUser iu = new ImpersonateUser();
            iu.Impersonate("domain", "userName", "password");
            //your code
            iu.Undo();

Comments

  • Anonymous
    February 03, 2009
    works! though how can I accomplish same thing via web.config on IIS7? Thanks

  • Anonymous
    February 11, 2009
    A very useful addition to my class library! Thank you!

  • Anonymous
    March 15, 2009
    FileStream data type is a very important feature of SQL Server 2008 and gradually getting popular amongst

  • Anonymous
    April 19, 2009
    When program was performing,The error is shown: Logon failure: unknown user name or bad password. please help me

  • Anonymous
    June 02, 2009
    In answer to Mettlus: web.config <configuration>   <system.web>    <identity impersonate="true" userName="DOMAINUSERNAME" password="PASSWORD" />   </system.web> </configuration> However, it may not be wise to let every session have impersonation.

  • Anonymous
    June 29, 2009
    I've been looking for some time for code that will allow me to perform an identity impersonate within a HttpModule and this code did exactly what I needed. Thanks.

  • Anonymous
    June 29, 2009
    Please giuide me the domain name is the Server Machine name or Remote Machine name?

  • Anonymous
    September 30, 2009
    I rarely post in these things but I just wanted to let you know I really liked this code - and it did exactly what I needed.

  • Anonymous
    October 28, 2009
    Great Code; Works Perfectly. Thank you for that

  • Anonymous
    November 03, 2009
    Excellent code, helped me a lot

  • Anonymous
    January 13, 2010
    The comment has been removed

  • Anonymous
    March 04, 2010
    If you want to use it in a using block, use this code instead:    public class ImpersonatedUser : IDisposable    {        private string _domain = "";        private string _username = "";        private string _password = "";        public ImpersonatedUser(string Domain, string Username, string Password)        {            _domain = Domain;            _username = Username;            _password = Password;            Impersonate();        }        [DllImport("advapi32.dll", SetLastError = true)]        public static extern bool LogonUser(string User, string Domain, string Password, int LogonType, int LogonProvider, ref IntPtr Token);        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]        public extern static bool CloseHandle(IntPtr handle);        private static IntPtr tokenHandle = new IntPtr(0);        private static WindowsImpersonationContext impersonatedUser;        // If you incorporate this code into a DLL, be sure to demand that it        // runs with FullTrust.        /// <summary>        /// Impersonates another Windows user        /// </summary>        /// <param name="Domain">The domain of the user to impersonate</param>        /// <param name="Username">The username of the user to impersonate</param>        /// <param name="Password">The password of the user to impersonate</param>        [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]        private void Impersonate()        {            //try            {                // Use the unmanaged LogonUser function to get the user token for                // the specified user, domain, and password.                const int defaultProvider = 0;                // Passing this parameter causes LogonUser to create a primary token.                const int interactive = 2;                tokenHandle = IntPtr.Zero;                // ---- Step - 1                // Call LogonUser to obtain a handle to an access token.                bool returnValue = LogonUser(_username, _domain, _password, interactive, defaultProvider, ref tokenHandle);                if (false == returnValue)                {                    int ret = Marshal.GetLastWin32Error();                    throw new System.ComponentModel.Win32Exception(ret);                }                // ---- Step - 2                WindowsIdentity newId = new WindowsIdentity(tokenHandle);                // ---- Step - 3                impersonatedUser = newId.Impersonate();            }        }        // Stops impersonation        public void Undo()        {            impersonatedUser.Undo();            // Free the tokens.            if (tokenHandle != IntPtr.Zero)                CloseHandle(tokenHandle);        }        #region IDisposable Members        public void Dispose()        {            Dispose(true);            GC.SuppressFinalize(this);        }        protected virtual void Dispose(bool Disposing)        {            if (Disposing)            {                _domain = null;                _username = null;                _password = null;            }            if (impersonatedUser != null)                Undo();            impersonatedUser = null;        }        ~ImpersonatedUser()        {            Dispose(false);        }        #endregion    } Then you can say: using (new ImpersonatedUser(domain, username, password)) {    // You are the impersonated user inside here }

  • Anonymous
    June 01, 2010
    sdsds

  • Anonymous
    August 15, 2010
    Yes perfect! Just what I was looking for! Thanks

  • Anonymous
    August 15, 2010
    Yes perfect! Just what I was looking for! Thanks

  • Anonymous
    September 12, 2010
    thanx lott... After 2 days my problem is solved... thank you. perfect Code.  

  • Anonymous
    October 12, 2011
    Exactly what I need, but LogonUser returns false every time, I'm sure the credentials are correct...

  • Anonymous
    October 13, 2011
    Thank you, Sir! Thank you, thank you, thank you!!

  • Anonymous
    February 02, 2012
    The comment has been removed

  • Anonymous
    July 22, 2012
    Hi. Regarding:        private static IntPtr tokenHandle = new IntPtr(0);        private static WindowsImpersonationContext impersonatedUser; Those two fields are declared static. I'd like to know (if anyone's still checking this blog):-

  1. Are there any benefits in declaring those variables as  static ?
  2. Are there any consequences (ie: danger) by having those two as static ? I'm talking about using this in ASP.NET environment. Cheers.
  • Anonymous
    May 22, 2015
    have a requirement, where I need to impersonate a logon user using the database account (the database account has access to system tables). I don't want to expose the password, by providing in a web.config file. is there a way to impersonate the logon user using database account without providing the password.