The WindowsIdentity class offers a constructor that accepts a user principal name (username@domain.int) and doesn't require the password. This sounds like a great way to get a token for impersonation but there are some limitations. First of all the account must be an AD account and...

  1. To use it on the network you must use constrained delegation to grant permission to the source server to generate tokens (And mark restricted accounts as not authorized for delegation) and also which target servers can be accessed with the token generated.
  2. To use it locally to access secured resources (Like files, etc) the process needs to have the trusted computing base priviledge which is root access to the box.

Keith Brown covers this here in detail. Unfortunately if you need to impersonate a LSA account or you cant/dont want to use constrained delegation you have to use the LogonUser API call to get a token to pass to the WindowsIdentity constructor. This call requires the domain, username and password. The WindowsIdentity class doesent offer a constructor that does this so you have to roll your own. Below is a simple class I whipped up that will do this.

Interesting aside, the SafeUserTokenHandle class is actually defined in the FCL but marked internal. There are actually a number of SafeHandle derived classes in System.dll (Under the Microsoft.Win32.SafeHandles namespace). So if you need a SafeHandle for a handle for a particular API call you may be able to snag one here for "free" with Reflector.

Some further reading on this subject; MSDN - How To: Use Impersonation and Delegation in ASP.NET 2.0, The .NET Developer's Guide to Windows Security (Or free online here!) and Professional ASP.NET 3.5 Security, Membership, and Role Management with C# and VB.

Here is the usage:

using (WindowsImpersonationContext context = 
        Impersonation.Impersonate("domain", "username", P@$$w0rd, LogonSessionType.Network))
{
    //Do something...
}

Here is the class:

using System;
using System.ComponentModel;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Security.Principal;
using System.Threading;
using Microsoft.Win32.SafeHandles;

public static class Impersonation
{
    #region Public Methods

        public static WindowsImpersonationContext Impersonate(
            string domain, string username, string password, LogonSessionType sessionType)
        {
            WindowsImpersonationContext impersonationContext = null;
            SafeUserTokenHandle token;

            if (LogonUser(
               username,
               domain,
               password,
               sessionType,
               LogonProvider.Default,
               out token))
            {
                using (token)
                {
                    impersonationContext = WindowsIdentity.Impersonate(
                        token.DangerousGetHandle());
                }
            }
            else
                throw new Win32Exception(Marshal.GetLastWin32Error());

            return impersonationContext;
        }

    #endregion

    #region Native Methods

        [DllImport("advapi32.dll", SetLastError = true)]
        private static extern bool LogonUser(
          string principal,
          string authority,
          string password,
          LogonSessionType logonType,
          LogonProvider logonProvider,
          out SafeUserTokenHandle token);

        public enum LogonSessionType : uint
        {
            Interactive = 2,
            Network,
            Batch,
            Service,
            NetworkCleartext = 8,
            NewCredentials
        }

        private enum LogonProvider : uint
        {
            Default = 0, // default for platform (use this!)
            WinNT35,     // sends smoke signals to authority
            WinNT40,     // uses NTLM
            WinNT50      // negotiates Kerb or NTLM
        }

    #endregion

    #region SafeTokenHandle Class

        [SuppressUnmanagedCodeSecurity, 
         HostProtection(SecurityAction.LinkDemand, MayLeakOnAbort=true)]
        private sealed class SafeUserTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
        {
            internal SafeUserTokenHandle() : base(true) { }

            internal SafeUserTokenHandle(IntPtr existingHandle, bool ownsHandle) : 
                base(ownsHandle)
            {
                base.SetHandle(existingHandle);
            }

            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), 
             DllImport("kernel32.dll", SetLastError=true, ExactSpelling=true)]
            private static extern bool CloseHandle(IntPtr handle);

            protected override bool ReleaseHandle()
            {
                return CloseHandle(base.handle);
            }
        }

    #endregion
}