/// <summary> /// Impersonates the specified user account. /// </summary> /// <param name="userName">Name of the user.</param> /// <param name="domainName">Name of the domain.</param> /// <param name="password">The password. <see cref="String"/></param> /// <param name="logonType">Type of the logon.</param> /// <param name="logonProvider">The logon provider.</param> /// /// <param name="impersonationAction">A callback to perform during the impersonation initialization.</param> public virtual void Impersonate(string userName, string domainName, SecureString password, LogonType logonType, LogonProvider logonProvider, Action <IntPtr> impersonationAction = null) { UndoImpersonation(); IntPtr logonToken = IntPtr.Zero; IntPtr logonTokenDuplicate = IntPtr.Zero; IntPtr passwordPtr = new IntPtr(); passwordPtr = Marshal.SecureStringToGlobalAllocUnicode(password); bool logonValue = false; try { // revert to the application pool identity, saving the identity of the current requestor this._wic = WindowsIdentity.Impersonate(IntPtr.Zero); // do logon & impersonate logonValue = Win32NativeMethods.LogonUser( userName, domainName, passwordPtr, (int)logonType, (int)logonProvider, ref logonToken); if (logonValue) { Win32NativeMethods.SECURITY_ATTRIBUTES sa = new Win32NativeMethods.SECURITY_ATTRIBUTES(); sa.nLength = (uint)Marshal.SizeOf(sa); if (Win32NativeMethods.DuplicateTokenEx( logonToken, Win32NativeMethods.TOKEN_ASSIGN_PRIMARY | Win32NativeMethods.TOKEN_DUPLICATE | Win32NativeMethods.TOKEN_QUERY, ref sa, (int)Win32NativeMethods.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, (int)Win32NativeMethods.TOKEN_TYPE.TokenPrimary, ref logonTokenDuplicate)) { // Looks like it is working without impersonating. To be revisited. ////var wi = new WindowsIdentity(logonTokenDuplicate); ////wi.Impersonate(); // discard the returned identity context (which is the context of the application) ////this.IsImpersonating = true; if (impersonationAction != null) { impersonationAction(logonTokenDuplicate); } } else { throw new Win32Exception(Marshal.GetLastWin32Error()); } } else { throw new Win32Exception(Marshal.GetLastWin32Error()); } } finally { Marshal.ZeroFreeGlobalAllocUnicode(passwordPtr); if (logonToken != IntPtr.Zero) { Win32NativeMethods.CloseHandle(logonToken); } if (logonTokenDuplicate != IntPtr.Zero) { Win32NativeMethods.CloseHandle(logonTokenDuplicate); } } }