Nothing new here. I just wanted to save this code snippet because it's popped up a few times in the past year and I have to go find it over and over. At least this will make it a little easier for me. This is by no means an authoritative reference -- it's simply what I have used. If you know of something I'm missing, please let me know.
First, you'll need to import the Win32 LogonUser() function:
public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);
The only question you probably have is about the logon type and provider parameters. The only provider I know of is the default, 0, which uses "negotiate" (Kerberos, then NTLM) for Windows XP/Server 2003 and later machines. Windows 2000 defaults to NTLM. If you don't know the difference, let me know and I'll explain that in more detail. Here are a list of logon types:
- Interactive (2) -- Intended for interactive use (duh) with something like terminal server or executing a remote shell. This type caches credentials for disconnected operations.
- Network (3) -- Intended for high performance servers to authenticate plain-text passwords.
- Batch (4) -- Intended for batch servers, which act on behalf of the user without his/her direct intervention. Typically used to process many plain-text auth attempts at a time.
- Service (5) -- Intended for service accounts, which have the "service" privilege enabled -- don't ask me what that is because I don't know.
- Unlock (7) -- Intended for GINA DLLs (whatever that is) that will interactively use the machine. This type includes some auditing.
- Clear Text (8) -- Intended for double-hop impersonation scenarios where credentials will be sent to the target server to allow it to also impersonate the user. As I understand it, this is what IIS "Basic" authentication uses. To perform a double-hop, you'll actually have to do a few other things. I won't get into that here, but let me know if that'd be of interest.
- New Credentials (9) -- Clones current credentials and uses new credentials for outbound connections. Supposedly, this doesn't work with the default provider -- it requires the WINNT50 provider, whatever that is.
The following is a list of the supported providers. I don't know anything about the non-default ones, but figured I'd list them for completeness..
- Default (0) -- "Negotiate" (Kerberos, then NTLM) for Windows XP/Server 2003 and later; NTLM for Windows
- NT 3.5 (1)
- NT 4.0 (2)
- NT 5.0 (3) -- Required for the "new credentials" logon type.
Next, well... just use it. As you can see, the last parameter in the LogonUser() function is an out parameter for a token which represents the user. This is key. All you need to do is initialize a WindowsIdentity instance with this token and you're well on your way.
public static WindowsIdentity GetIdentity(string domain, string userName, string password)
bool success = LogonUser(userName, domain, password, 2, 0, out token);
return (success) ? new WindowsIdentity(token) : null;
Pretty simple. Of course, we still aren't there, yet. Now that you have the identity, you most likely want to impersonate it. Luckily, this is a simple 2-liner... well, technically two 1-liners. I should also say that, if you want to do impersonation with an already-obtained WindowsIdentity (and you don't have a password), you'll start here.
ImpersonationContext context = GetIdentity("mydomain", "me", "mypassword").Impersonate();
That's it. Enjoy!