0

I'm using the following Microsoft example. Every time the WindowsIdentity instance calls .Impersonate(), nothing happens. No error, no impersonation.
Both before and after the call, the current identity is always the AppPool identity.
I've also tried another example found online, the Impersonator class, and the same thing happens.

The only modification I've made to those examples is changing LOGON32_LOGON_INTERACTIVE to LOGON32_LOGON_NETWORK in the LogOnUser call, since using Interactive always returned a 0 error.

It's an ASP.NET 4.0 app running on a Win2k8 server trying to impersonate a user in AD.

EDIT: I hadn't mentioned this originally, but I modified the Microsoft example and turned it into a class so that I can could it from my ASP.NET app. I also have impersonate=true in web.config.

eych
  • 1,262
  • 2
  • 16
  • 37
  • Do you want the entire ASP.Net app to impersonate a certain user, or do you just want to impersonate a different user temporarily (e.g. during a method call)? – Andrew Stephens May 08 '12 at 15:11
  • Temporarily...for file access. Each user logs in to the app (forms login). The app authenticates the user against the AD of the app server. Generally, the user can work the app under the apppool identity. However, some users may need file access. I want to then impersonate as the user (since I have their login details). Also, not all users will have file access rights on the server. – eych May 08 '12 at 15:51

3 Answers3

1

I eventually found a helper class where I had done something similar a couple of years ago. The helper implements IDisposable, so just wrap your file access code in a "using" like this:-

using (Impersonate imp = new Impersonate())
{
    // Code in here will run under the identity specified in the helper
}

And here is the code for the helper class (I've removed the "usings" to save some space). You'll notice the user account is hardcoded in the constructor:

internal class Impersonate : IDisposable
{
    private const int LOGON32_LOGON_INTERACTIVE = 2;
    private const int LOGON32_PROVIDER_DEFAULT = 0;

    private bool _disposed = false;
    private WindowsImpersonationContext _context = null;

    [DllImport("advapi32.dll")]
    private static extern int LogonUserA(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern int DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken);

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern bool RevertToSelf();

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    private static extern bool CloseHandle(IntPtr handle);

    internal Impersonate()
    {
        WindowsIdentity tempWindowsIdentity;
        IntPtr token = IntPtr.Zero;
        IntPtr tokenDuplicate = IntPtr.Zero;

        string domain = "<whatever>";
        string username = "<whatever>";
        string password = "<whatever>";

        try
        {
            if (RevertToSelf())
            {
                if (LogonUserA(username, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0)
                {
                    if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                    {
                        tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                        _context = tempWindowsIdentity.Impersonate();
                    }
                }
            }
        }
        finally
        {
            if (token != IntPtr.Zero)
            {
                CloseHandle(token);
            }

            if (tokenDuplicate != IntPtr.Zero)
            {
                CloseHandle(tokenDuplicate);
            }
        }
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                // Dispose any managed resources here.
            }

            // Stop the impersonation.
            _context.Undo();

            _disposed = true;

        }
    }
}

Give it a go and let me know how you get on...

Andrew

Andrew Stephens
  • 9,413
  • 6
  • 76
  • 152
  • that's very similar to what I have. The problems is at the `tempWindowsIdentity.Impersonate()` call. It doesn't impersonate and it doesn't throw an error. The current identity stays the same. The problem must be a server/AD setting or some permission issue as all examples over the net are similar to this. Thanks anyway. – eych May 09 '12 at 18:43
  • At least you know it's not your code. Sounds like a privilege issue. Have you tried getting the last error after calling LogonUser (see here: http://stackoverflow.com/questions/996429/logonuser-and-delegation). Also try giving your ASP.Net process account "act as part of the operating system" privilege on the server, and check that the account you are trying to impersonate is able to log-on to the server. – Andrew Stephens May 10 '12 at 08:39
0

The example you link is for a console application. If you have an ASP.Net web application where you want your code to be executed under the security context of the visitor you can enable ASP.Net impersonation in the IIS authentication settings (in the IIS manager MMC snap in).

Bjørn van Dommelen
  • 1,057
  • 7
  • 13
  • see my edit...I turned the console app into a class. My main concern is the details of the actual impersonation. – eych May 08 '12 at 14:14
  • Your situation looks an awful lot like http://stackoverflow.com/questions/1066275/impersonate-using-forms-authentication Although it IS possible your situation generally leans towards using windows authentication instead of forms authentication (why forms? because the login form looks nicer? Is that REALLY worth all that money you're now spending on hacking out an essentially unsupported solution?) Also keep in mind that every impersonation done as stated below will require a full user logon which might make your web applciation a lot slower... – Bjørn van Dommelen May 09 '12 at 14:30
  • It's forms because the user can log in from any computer. And a login form is necessary because of users' request. – eych May 09 '12 at 18:47
0

Giving write access to the App_Data folder for the Users group fixed the issue. Not sure what that has to do with impersonation though.

eych
  • 1,262
  • 2
  • 16
  • 37