Imperatively Impersonate a User

In this example we will Imperatively Impersonate a User so that we can run code with increased permissions and then undo the Impersonation so that we are running using the standard ASP.NET permissions.

The ImpersonationSettings Class is used to get the Username, Domain and Password from the Application Settings


using System;
using System.Configuration;

namespace ImpersonateUserTestApp
{
    public class ImpersonationSettings
    {
        public string Username { get; set; }
        public string Password { get; set; }
        public string Domain { get; set; }

        public ImpersonationSettings()
        {
            Username = GetAppSetting("Impersonation.Username");
            Password = GetAppSetting("Impersonation.Password");
            Domain = GetAppSetting("Impersonation.Domain");
        }

        private string GetAppSetting(string key)
        {
            if (string.IsNullOrEmpty(ConfigurationManager.AppSettings[key]))
                throw new NullReferenceException(string.Format("Application Setting '{0}' is Null or Empty", key));

            return ConfigurationManager.AppSettings[key];
        }
    }
}

The Application Settings are in the web.config file


	
		
		
		
	

The UserImpersonation takes the ImpersonationSettings in it constructor.


using System;
using System.Runtime.InteropServices;
using System.Security.Principal;

namespace ImpersonateUserTestApp
{
    public class UserImpersonation
    {
        public const int Logon32LogonInteractive = 2;
        public const int Logon32ProviderDefault = 0;

        private readonly ImpersonationSettings _settings;
        private WindowsImpersonationContext _impersonationContext;

        public UserImpersonation(ImpersonationSettings settings)
        {
            _settings = settings;
        }

        [DllImport("advapi32.dll")]
        public static extern int LogonUserA(String lpszUserName,
                                            String lpszDomain,
                                            String lpszPassword,
                                            int dwLogonType,
                                            int dwLogonProvider,
                                            ref IntPtr phToken);

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern int DuplicateToken(IntPtr hToken,
                                                int impersonationLevel,
                                                ref IntPtr hNewToken);

        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool RevertToSelf();

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public static extern bool CloseHandle(IntPtr handle);

        public bool Impersonate()
        {
            WindowsIdentity windowsIdentity;
            IntPtr token = IntPtr.Zero;
            IntPtr tokenDuplicate = IntPtr.Zero;

            if (RevertToSelf())
            {
                if (LogonUserA(_settings.Username, _settings.Domain, _settings.Password, Logon32LogonInteractive,
                               Logon32ProviderDefault, ref token) != 0)
                {
                    if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                    {
                        windowsIdentity = new WindowsIdentity(tokenDuplicate);
                        _impersonationContext = windowsIdentity.Impersonate();

                        if (_impersonationContext != null)
                        {
                            CloseHandle(token);
                            CloseHandle(tokenDuplicate);

                            return true;
                        }
                    }
                }
            }

            if (token != IntPtr.Zero)
                CloseHandle(token);

            if (tokenDuplicate != IntPtr.Zero)
                CloseHandle(tokenDuplicate);

            return false;
        }

        public void UndoImpersonation()
        {
            _impersonationContext.Undo();
        }
    }
}

When you call the Impersonate method it starts the Impersonation.

Once you have completed the actions that require increased permissions you call the UndoImpersonation method to stop the Impersonation.

You could use this in a standard ASPX when you need to increase your permissions for accessing a network drive for example.


using System;
using System.Web.UI;

namespace ImpersonateUserTestApp
{
    public partial class _Default : Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            ImpersonationSettings settings = new ImpersonationSettings();

            UserImpersonation userImpersonation = new UserImpersonation(settings);

            try
            {
                userImpersonation.Impersonate();
                //perform action with increased permissions
            }
            finally
            {
                userImpersonation.UndoImpersonation();
            }
        }
    }
}

Notice now the Impersonation is performed in the Try Finally, this will force the Impersonation to undo even if there is a problem, therefore not leaving your web application with increased permissions.

You can download the User Impersonation project here



Comments

  1. livelybrowsers October 19th

    Comment Arrow

    Thanks for good stuff


  2. roclafamilia October 21st

    Comment Arrow

    Helpful blog, bookmarked the website with hopes to read more!


  3. Zapacila October 30th

    Comment Arrow

    Perfect!! Worked with SharePoint 2007 now i can programatically login a user.


  4. Somansh Kumar January 3rd

    Comment Arrow

    Awesome tutorial man!!
    Kudos


Add Yours

  • Author Avatar

    YOU


Comment Arrow




About Author

Robert

Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning hands down.