locked
Make web api run as Authenticated Windows user NOT App Pool credential RRS feed

  • Question

  • User369345748 posted

    I have an MVC intranet application with authenticates a user with Windows Authentication, & which successfully shows their credentials

    Within one of the controllers , I call a Restful web service. This needs to be done with the credential of the authenticated user ( EG Fred Smith) , as the service checks who is running it & what they can do & tailors the data returned according to their permissions & other attributes.  
    When I deploy these to a server, the web service call always runs with the app pool id , which the restful service runs under instead of the authenticated user ( Fred Smith ) .  
    The code is similar to this below
               WebClient Wclient = new WebClient();
               Wclient.UseDefaultCredentials = true;
               Wclient.Credentials = CredentialCache.DefaultNetworkCredentials;
               string returnVal = Wclient.DownloadString("https://myRestful/Service) 
    I have tried the following things but so far nothing makes the web service run as Fred Smith: 
     Wclient.Credentials = CredentialCache.DefaultNetworkCredentials; 
     Wclient.Credentials = CredentialCache.DefaultCredentials; 
    In IISManager  Ensure that Anonymous Auth is disabled & Windows Authentication is enabled for both apps 
    In IISManager Enabled Impersonation on the Restful API 
    In all situations, the web service runs as GeneralAppPool not Fred Smith or Joe Bloggs
    Any suggestions gratefully received
    Thursday, July 11, 2019 3:29 PM

All replies

  • User-474980206 posted

    as ntlm has a one hop rule, you will need to switch to kerberos and delegation. see:

      https://support.microsoft.com/en-us/help/810572/how-to-configure-an-asp-net-application-for-a-delegation-scenario

    you could  also use basic authentication with windows accounts, and convert the login windows token to a primary token. and then impersonate  the token before making the call.

    convert to primary:

       https://docs.microsoft.com/en-us/windows/win32/api/securitybaseapi/nf-securitybaseapi-duplicatetokenex

    impersonate:

      https://docs.microsoft.com/en-us/dotnet/api/system.security.principal.windowsidentity.impersonate?view=netframework-4.8

    note: this only works with basic authentication. you can not convert a windows authentication token to a primary.

    Thursday, July 11, 2019 3:48 PM
  • User369345748 posted

    Hi Bruce Many thanks for the quick response.   

    There's a couple of issues I did not mention

    Both the rest api & the calling application sit on the same server, so my understanding is that Kerberos ( which is notoriously tricky to implement correctly ) may not be needed. 

    All the articles I have seen on impersonation,  do it by logging on with a userName string and a Password string,  which as I am sure you know is problematic on a number of levels.

    Friday, July 12, 2019 8:12 AM
  • User-474980206 posted
    If the calling program created the token, (not passed to it), then the token can be converted to a primary. The web api should convert the token to a primary. As there can only be one user (the calling program), then you probably don’t need to create impersonation threads.

    As there is only one user in your scenario, not sure why it’s not easier to make the app domain the correct user.
    Monday, July 15, 2019 4:16 PM
  • User369345748 posted

    Hi Bruce 

    Thanks for this.   I was able to get this working with impersonation in the calling code 

    WebClient Wclient = New WebClient();

    Wclient.UseDefaultCredentials = true;

    Wclient.Credentials = CredentialCache.DefaultNetworkCredentials;

    IIdentity contextId = HttpContext.Current.User.Identity;

    WindowsIdentity userId = (WindowsIdentity)contextId;

    WindowsImpersonationContext imp = userId.Impersonate();

    string data = Wclient.DownloadString;

    imp.Undo();

    Tuesday, July 16, 2019 2:55 PM