简体   繁体   中英

Call Web API from MVC Application with Integrated Windows Authentication

I have an MVC Application and an associated Web API project that are both hosted on a remote server on IIS. They share the same application pool. Whenever I try to make a call to the Web API from the MVC Application I get a 403 error, which appears to be coming from bad credentials being passed by the HttpClientHandler. I have

UseDefaultCredentials = true 

and I have tried setting

Credentials = CredentialCache.DefaultNetworkCredentials

but neither of these allows the API request to go through.

Setting the Application Pool to use my AD Username/Password allows all API requests to go through, and also calling the API directly from Postman returns data properly.

My assumption is that IIS AppPool[Pool Name] is getting forwarded in the request, and the proper credentials are never passed. Is there anyway around this without making the API unsecure (Ie only a couple of domain groups should be able to access it)?

Example of a call I'm making to the API from the MVC application

    public async Task<HttpResponseMessage> CreateIncident(Incident model)
    {
        using (var client = new HttpClient(new HttpClientHandler { UseDefaultCredentials = true }))
        {
            var newIncident = new StringContent(JsonConvert.SerializeObject(model), Encoding.UTF8, "application/json");
            var response = await client.PostAsync(hostUri, newIncident);
            return response;
        }
    }

Without more information it is hard to say for sure, but the issue is likely due to the double-hop authentication you are attempting.

  1. the client application (browser in the case of a website) authenticates the user the client sends
  2. the authentication to the server (MVC application)
  3. the MVC application then tries to pass the authentication along to the web service

When I needed to do a similar task, I was unable to get HttpClient to work. I tried a number of suggested solutions from this question, How to get HttpClient to pass credentials along with the request? . While it was informative -- specifically, this portion of BlackSpy's answer explained why:

What you are trying to do is get NTLM to forward the identity on to the next server, which it cannot do - it can only do impersonation which only gives you access to local resources.

I ended up using WebClient (with required targeting .NET framework) with something like this in the MVC application (downloading a file from the web api, in this case):

private async Task GetFileAsync(Identity identity, string serviceAddress, Stream stream)
{
    var windowsIdentity = Identity as WindowsIdentity;

    if (windowsIdentity == null)
    {
        throw new InvalidOperationException("Identity not a valid windows identity.");
    }

    using (windowsIdentity.Impersonate())
    {
        using (var client = new WebClient { UseDefaultCredentials = true })
        {
            var fileData = await client.DownloadDataTaskAsync(serviceAddress);
            await stream.WriteAsync(fileData, 0, fileData.Length);
            stream.Seek(0, SeekOrigin.Begin);
        }
    }
}

While the requirement to target the full framework prevents this from being a .NET Core solution, but it looks like it has been added since then.

Add WebClient to new System.Net.WebClient contract

This PR ports System.Net.WebClient to corefx. The code is mostly taken from desktop and then cleaned up a bit stylistically. The only major code rewrite was removing hundreds of lines of complicated APM callback-based code and replacing it with a few core async methods. There's still plenty of more cleanup that can be done, but functionally this is sufficient.

Without seeing the code its hard to say. Have you tried without setting the Credentials parameter? I would run fiddler and compare the request sent by the MVC application and Postman.

You can find out how to impersonate an already authenticated (windows) user at this GitHub discussion page: https://github.com/aspnet/Home/issues/1805

ilanc has a really good demo with a link towards the bottom.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM