Search code examples
c#windows-authenticationimpersonation

Impersonation works with local shared file, but does not work with remote one


I have a .net/c# web app (web api) with windows authentication. The service is hosted on my local computer, IIS 10. Application pool identity set to me, currently logged in windows user. Computer is in active directory domain.

I want to access shared file using account, currently logged in to the app. File has appropriate permissions. For this purposes I use impersonation like this:

    if (HttpContext.Current.User.Identity is WindowsIdentity windowsIdentity)
       {
           using (windowsIdentity.Impersonate())
           {
                FileStream stream = new FileStream(@"\\server\share\file.ext", FileMode.Open, FileAccess.Read);
           }
       }

I logging in with current windows account, the same as set in app pool identity. This works fine with a shared file on a local computer, where the app is hosted. But does not work with a remote shared file, located on another computer. The other computer is in active directory domain too.

From a hosting computer I can access shared file using windows explorer or my browser. Also if I do not impersonate user, .net trying to access shared file with application pool identity account(set to the same user, me) and it succeeded for both, local and remote files.

It also works with impersonated identity got from LogonUser method from advapi32.dll. But it requires user password and I do not want to request password from user, already logged in to app.

What am i doing wrong?

Update: If a shared file located on hosting machine, then logon event generated by windows (security tab in event viewer) shows the right user. If a shared file located on another machine, then logon event generated by windows on this machine shows the anonymous user. So, account somehow lost.

Update 2: Impersonation works if I run site on IIS like localhost(localhost in url). But if I run it using ip or site name it stops working.

Update 3: Wireshark shows the request for getting ticket(to access shared file server) for delegation fails with error "KRB5KDC_ERR_BADOPTION NT Status: STATUS_NOT_FOUND". Delegation for application pool user allowed in AD. The same ticket(for cifs/fileshareservername) without delegation can be successfully retrieved(wireshark shows) when doing Dir command in cmd. Seems like problem in AD.


Solution

  • It started working for me with the following settings.

    IIS:

    1. Application pool identity set to a specific user(let's say IISUser).
    2. Windows authentication enabled for IIS site. Kernel mode enabled (important!).

    All other magic is happening in Active directory:

    1. Computer with shared files has an SPN: cifs/%computer_name%.
    2. Hosting computer(where IIS installed) is trusted for delegation. Delegation tab -> Trust this computer for delegation to specified services only -> Use any authentication protocol. Then select SPN from item 1. Important: you should select computer SPN, not IISUser SPN.
    3. IISUser is trusted for delegation for SPN from item 1.