C# : Windows Impersonation

May 4, 2010 by Christoff Truter C#  

The WindowsImpersonationContext class provides us with the ability to impersonate an user.

In the following post we're going to look at how to write to a protected shared folder using impersonation.

You will notice that the WindowsImpersonationContext class doesn't have a constructor, nor any static methods defined - one can however get an instance of this class via the Impersonate static method in the WindowsIdentity class, observe:

using (WindowsImpersonationContext context = WindowsIdentity.Impersonate(token))
{
	// Some operation requiring impersonation
}

Note, the WindowsImpersonationContext class implements the IDisposable interface which enables us to use the using clause - code out of scope (running outside) the using clause won't be executed within context of the impersonated user.

In order for our impersonation to work, we need to pass a primary token to our method, to retrieve the token, we'll need to import a method from the "Advanced Services" assembly (advapi32.dll) like this:
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

And an import to dispose of the token.
[DllImport("kernel32.dll")]
public static extern bool CloseHandle(IntPtr token);

You might have noticed the LogonType and LogonProvider parameters in the LogonUser method, we need to tell the API by which means authentication must happen - to simplify this, I created two enum's:
enum LogonType
{
	Interactive = 2,
	Network = 3,
	Batch = 4,
	Service = 5,
	Unlock = 7,
	NetworkClearText = 8,
	NewCredentials = 9
}

enum LogonProvider
{
	Default = 0,
	WinNT35 = 1,
	WinNT40 = 2,
	WinNT50 = 3
}

I am not going to go into too much depth about these providers, but lets have a quick look at the Interactive and NewCredentials LogonTypes.

Using the Interactive LogonType will look something like this:
IntPtr token = IntPtr.Zero;
bool valid = LogonUser("username",
			"yourdomain.com",
			"password",
			(int)LogonType.Interactive,
			(int)LogonProvider.Default,
			ref token);
if (valid)
{            
	using (WindowsImpersonationContext context = WindowsIdentity.Impersonate(token))
	{
		CloseHandle(token);
		File.WriteAllBytes(@"\\yourserver\someshare\test.txt", new byte[] { });
	}
}

Now this is all nice and all when we're impersonating someone thats on the same domain as us, but what about impersonating outside our domain?

This is where I found the NewCredentials LogonType useful, since it authenticates cross domain:
IntPtr token = IntPtr.Zero;
LogonUser("username",
			"yourdomain.com",
			"password",
			(int)LogonType.NewCredentials,
			(int)LogonProvider.WinNT50,
			ref token);

using (WindowsImpersonationContext context = WindowsIdentity.Impersonate(token))
{
	CloseHandle(token);
	File.WriteAllBytes(@"\\yourserver\someshare\test.txt", new byte[] { });
}

I didnt include the valid bool in the preceding snippet, this is because you'll find that the LogonUser method seems to always return true when using the NewCredentials LogonType since authentication only happens when you're accessing the resource, in this case the File.WriteAllBytes method.

Leave a Comment


March 1, 2013 by Anonymous

What a small but great info. Thank you so much. You saved my ass

January 25, 2013 by sagar

I am still getting error as - The trust relationship between this workstation and the primary domain failed.

August 13, 2012 by Anonymous

This is pure gold. Thanks!

July 30, 2012 by kenan hancer

Thank you very much

Local Account April 25, 2012 by Anonymous

Do you need a local account with the same name and pw as the account on the different domain?

Great November 30, 2011 by Fractalist

Thank you very much! This is exactly what I was looking for. Have a nice day, friend.

Anonymous December 24, 2010 by Anonymous

Thanks a lotto

October 27, 2010 by Jay

Well written. Save me heaps of time.

Thanks October 26, 2010 by Albert

Thanks A lot many times. This saved me my day. Thanks, Albert

Thank you! September 8, 2010 by wiygN

Thank you! Your post was exactly what I needed! You saved my time! Best regards!


Latest Posts

Simple JavaScript Shop - Back to the future : Part 1

March 20, 2015

Getting my hands dirty with TypeScript

February 17, 2015

Quick and dirty look at TypeScript

January 29, 2015

My personal life in review

January 21, 2015

Quick rundown of possible new C# 6.0 features (perhaps, maybe - I think)

January 19, 2015

Proof of Concept - JavaScript Mediator Framework

January 13, 2015

JavaScript Tip - Benchmarking

January 7, 2015

Google's new and improved reCAPTCHA - simple PHP implementation

January 5, 2015

NASA missions to follow in 2015

January 3, 2015

Online content censorship - South Africa

January 2, 2015


Most Commented on Posts

Moving items between listboxes in ASP.net/PHP example

Move items between two listboxes in ASP.net(C#, VB.NET) and PHP
June 12, 2008

Simple WYSIWYG Editor

Creating a WYSIWYG textbox for your website is actually quite simple.
February 1, 2007

C# YouTube : Google API

Post on how to integrate with YouTube using the Google Data API
March 12, 2011

Populate a TreeView Control C#

Populate a TreeView control in a windows application.
August 27, 2009

Cross Browser Issues: Firefox Word Wrapping

Firefox word wrapping issues
June 9, 2008


Angular   ASP.NET   Astronomy   C#   C++   Coding Horrors   Comedy   Cross Browser   Design Patterns   Google API   IIS   Integration   JavaScript   Love and War   Microsoft Office   Personal   PHP   South Africa   SQL   Threading   TypeScript   Visual Basic   XML