Introduction

The term "Impersonation" in a programming context refers to a technique that executes the code under another user context than the user who originally started an application, i.e. the user context is temporarily changed once or multiple times during the execution of an application.

The reason for doing this is to perform tasks that the current user context of an application is not allowed to do. Of course you could grant the user executing an application more privileges, but usually this is a bad idea (due to security constraints) or impossible (e.g. if you don't have full administrative access to a machine to do so).

This article presents an easy-to-use class to impersonate a user. While writing this, I found out that Marc Merrit had written an article ("Windows Impersonation using C#") that uses the same Microsoft knowledge base code (from Q306158) that I have used. The code presented in my article differs in the fact that you could use it inside a using-block to safely release resources and that I use slightly more exceptions to report errors. But from a first look, both his and my article do the same job, so it's up to you to decide what to do.

Background

I wrote the Impersonator class because of a need to write a web page with ASP.NET to make a server reboot. In order to do this, I needed to impersonate the part of my code that does the actual reboot.

The constructor of the class internally calls the Windows function LogonUser through P/Invoke. Please see the MSDN documentation of the function for a full description of all three parameters (username, domain, password) to the constructor.

Please note: The user context that initiates the impersonation (i.e. not the user context to which it is switched to) needs to have the "Act as part of operating system" privilege set.

Using the code

To use the code, you simply construct the Impersonator class and pass the username, the domain and the password to the constructor. If you place an instance of the class inside a using-block, you need no further steps.

An example project demonstrating the technique is included in the download of this article (please look at the "Program.cs" for the main demonstration source file). Also the complete source code of the class is included inside the source file "Impersonator.cs".

To include the Impersonator class into your project, simply copy and add the source file "Impersonator.cs" to your project, so that it gets compiled with your project.

Conclusion

In this article, I've shown you a small class to quickly and easily impersonate a part of your code to run under another user context. Hopefully you'll find this class useful.

For questions, comments and remarks, please use the commenting section at the bottom of this article.

References

In addition to the links in the article, the following references might be of interest:

Share

About the Author

Uwe does programming since 1989 with experiences in Assembler, C++, MFC and lots of web- and database stuff and now uses ASP.NET and C# extensively, too. He has also teached programming to students at the local university.

In his free time, he does climbing, running and mountain biking. Recently he became a father of a cute boy.

On Windows 10 Pro within a Virtual Machine, the class failed on the LogonUser method. As other suggested for Windows Server, I changed LOGON32_LOGON_INTERACTIVE to 9 and it worked!
My VM is NOT in the domain, and my code is accessing another computer within the domain.

I also added a constructor with a NetworkCredential object, which already has the 3 parameters user/domain/pwd. It makes the use a bit more robust, avoiding switching the string...

Impersonator is working very fine.
Now, I am facing an issue using FileInfo.CopyTo since the source file is located on a folder that the impersonator doesn't have access right to. Actually the source file is located at Documents folder which is accessed only by the original logged user. How can I fix such issue?

'Error message: Logon failure: the user has not been granted the requested logon type at this computer'.

I've used this class for years but I've recently started getting this error message on Windows 2008 R2 servers. I'm trying to validate a service account has rights to connect a SQL database as part of an installer. Seems to still work fine on our old Windows 2003 servers, its just the new W2K8 R2 servers that are having this trouble.

Just wondering if anyone has encountered this error and how to resolve it.

I had a request from a client to add support for local user impersonation (e.g. MachineName\Administrator) when my application (that uses your amazing class) is accessing remote machines.

Through the power of google and StackOverflow I was able to add it without any major changes or breaking anything (AFAIK). I'm using an older version of your class [^] than the one available here but the changes should be fairly straightforward to you.

Thank you very much for posting this. It worked perfectly for what I needed to implement. I have a WPF app where I am uploading a file from the user's computer to a network file share (vault). The network file share only has a single user that can access it, and that is a user specifically created for this application. I can easily use the File.Copy() method to copy the file to the network file share as the user with your class.

Hi
I get the “Invalid token for impersonation - it cannot be duplicated” exception intermittently when I use this class.

I always use it as specified by the author:

using (new Impersonator(Username, Domain, Password))
{
//my code
}

but if I call a function that use this line of code, wait 5 minutes and then call it again I have a 30-20% chance that I will get the exception.
I think it has something to do with the problem mentioned here: [^]
but I don't know what changes (if any) I should do to the class.

couldn't solve this since no one replied but I did implement a retry mechanism (a while loop that depends on this exception message: "Invalid token for impersonation - it cannot be duplicated.") as it always seem to work on the second time.

I am a novice. We have web applications currently using this class in the Page_Load. Is there any way to call this class just once to establish impersonation for the entire web session? I tried moving the call to Session_Start - but having problems with that placement. thanks

I love this project! It does exactly what it says it does. I've been using it for a number of months on my 32-bit machine. I recently got a 64-bit machine, and I've been having trouble with it. The code I'm writing runs on the 32-bit architecture; however, every time I invoke the impersonation code, the screen flashes off an on a few times (after about 10 seconds) and the applications I had open are all mixed around. Whenever this happens, there is an event in the event log: