impersonation and BackgroundWorker
- by Lucian D
Hello guys,
I have a little bit of a problem when trying to use the BackgroundWorker class with impersonation. Following the answers from google, I got this code to impersonate
public class MyImpersonation{
WindowsImpersonationContext impersonationContext;
[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 impersonateValidUser(String userName, String domain, String password) {
WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
if (RevertToSelf()) {
if (LogonUserA(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();
if (impersonationContext != null) {
CloseHandle(token);
CloseHandle(tokenDuplicate);
return true;
}
}
}
}
if (token != IntPtr.Zero)
CloseHandle(token);
if (tokenDuplicate != IntPtr.Zero)
CloseHandle(tokenDuplicate);
return false;
}
}
It worked really well until I've used it with the BackgroundWorker class. In this case, I've added a impersonation in the the code that runs asynchronously. I have no errors, but the issue I'm having is that the impersonation does not work when it is used in the async method.
In code this looks something like this:
instantiate a BGWorker, and add an event handler to the DoWork event:
_bgWorker = new BackgroundWorker();
_bgWorker.DoWork += new DoWorkEventHandler(_bgWorker_DoWork);
in the above handler, a impersonation is made before running some code.
private void _bgWorker_DoWork(object sender, DoWorkEventArgs e) {
MyImpersonation myImpersonation = new MyImpersonation();
myImpersonation.impersonateValidUser(user, domain, pass)
//run some code...
myImpersonation.undoImpersonation();
}
the code is launched with
BGWorker.RunWorkerAsync();
As I said before, no error is thrown, only that the code acts as if I did't run any impersonation, that is with it's default credentials.
Moreover, the impersonation method returns true, so the impersonation took place at a certain level, but probably not on the current thread.
This must happen because the async code runs on another thread, so there must be something that needs to be added to the MyImpersonation class. But what?? :)
Thanks in advance,
Lucian