2

I am building an admin module for an intranet MVC application. This application implements Windows Authentication (users are automatically logged in).

Currently I base all the user experience based around their HttpContext.User.Identity data.

What I need to do is to be able to impersonate an user so I can replicate their experience if they are having problems.

With Forms Authentication this is very straight forward...

I tried replacing the IPrincipal.User object in the HttpContext but this only has a getter not a setter.

any pointers would be greatly appreciated.

Thanks.

dove
  • 20,469
  • 14
  • 82
  • 108
franklores
  • 375
  • 3
  • 14
  • Do you have the users password you want to impersonate? – Botonomous Mar 14 '14 at 13:50
  • I've answered assuming he has, don't see how you'd be allowed to if he didn't – dove Mar 14 '14 at 13:52
  • :) I would hope haha. Good answer. Nice use of advapi32.dll – Botonomous Mar 14 '14 at 13:55
  • This is the code I am using... I am basically not trying to get the user context, but data based on the user and some of that data comes from AD some from a database. I am them building a data object that is saved on the session. SessionData sessionData = new SessionData(); WindowsIdentity identity = new WindowsIdentity("user@email.org"); sessionData.UserData = uService.GetUserInfo(identity); if (Session["SessionData"] == null) { Session["SessionData"] = sessionData; } – franklores Mar 14 '14 at 15:39

1 Answers1

3
 using (new Impersonation()){
  // now working in context of whatever user you want
 }

and this is the class

 [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
    public class Impersonation : IDisposable
    {
    private readonly SafeTokenHandle _handle;
    private readonly WindowsImpersonationContext _context;

    //const int Logon32LogonNewCredentials = 9; 
    private const int Logon32LogonInteractive = 2;

    public Impersonation()
    {
        var domain = "your domain;
        var username = "the user";
        var password = "their password";
        var ok = LogonUser(username, domain, password, Logon32LogonInteractive, 0, out _handle);
        if (!ok)
        {
            var errorCode = Marshal.GetLastWin32Error();
            throw new ApplicationException(string.Format("Could not impersonate the elevated user.  LogonUser returned error code {0}.", errorCode));
        }
        _context = WindowsIdentity.Impersonate(_handle.DangerousGetHandle());
    }

    public void Dispose()
    {
        _context.Dispose();
        _handle.Dispose();
    }

    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);

    public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
    {
        private SafeTokenHandle()
            : base(true) { }

        [DllImport("kernel32.dll")]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [SuppressUnmanagedCodeSecurity]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool CloseHandle(IntPtr handle);

        protected override bool ReleaseHandle()
        {
            return CloseHandle(handle);
        }
    }
}
dove
  • 20,469
  • 14
  • 82
  • 108
  • For future reference, basically this solution is the same as [this SO answer](http://stackoverflow.com/a/7250145/540776), where there also seems to be a Github project + NuGet available. – superjos Feb 09 '15 at 17:26