Run part of your C# Code under a different user
In this article, I am re-covering the approach you can use to impersonate a different user for a specific section of your C# code.
I had a ASP.net project where pretty much everything can run using the IIS Service account, except for a certain call to a web service, where I needed to run it with a different service account, which was followed by other IO operations using the same account.
The way I approached this was by creating an IDisposable class which I could use to encapsulate my C# code and ensure that the inner code runs with any account.
1.The impersonator Class
This is the core class, it requires the following namespaces
using System;
using System.Security.Principal;
using System.Runtime.InteropServices;
using System.ComponentModel;
public class Impersonator : IDisposable { public Impersonator( string userName, string domainName, string password) { ImpersonateValidUser(userName, domainName, password); } public void Dispose() { UndoImpersonation(); } [DllImport("advapi32.dll", SetLastError = true)] private static extern int LogonUser( string lpszUserName, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern int DuplicateToken( IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken); [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern bool RevertToSelf(); [DllImport("kernel32.dll", CharSet = CharSet.Auto)] private static extern bool CloseHandle( IntPtr handle); private const int LOGON32_LOGON_INTERACTIVE = 2; private const int LOGON32_PROVIDER_DEFAULT = 0; private void ImpersonateValidUser( string userName, string domain, string password) { WindowsIdentity tempWindowsIdentity = null; IntPtr token = IntPtr.Zero; IntPtr tokenDuplicate = IntPtr.Zero; try { if (RevertToSelf()) { if (LogonUser( userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0) { if (DuplicateToken(token, 2, ref tokenDuplicate) != 0) { tempWindowsIdentity = new WindowsIdentity(tokenDuplicate); impersonationContext = tempWindowsIdentity.Impersonate(); } else { throw new Win32Exception(Marshal.GetLastWin32Error()); } } else { throw new Win32Exception(Marshal.GetLastWin32Error()); } } else { throw new Win32Exception(Marshal.GetLastWin32Error()); } } finally { if (token != IntPtr.Zero) { CloseHandle(token); } if (tokenDuplicate != IntPtr.Zero) { CloseHandle(tokenDuplicate); } } } private void UndoImpersonation() { if (impersonationContext != null) { impersonationContext.Undo(); } } private WindowsImpersonationContext impersonationContext = null; } }
2. Using it
Simply use a using {} as follow
using (Impersonator Context = new Impersonator("YourUserID","YourDomain","YourPassword")) { // What ever you put here, will run under the YourUserID account }