Call web API from MVC application with integrated Windows authentication

I have an MVC application and its associated web API project that are hosted on a remote server in IIS. They have the same application pool. Whenever I try to call the web API from an MVC application, I get a 403 error, which seems to come from the bad credentials passed by the HttpClientHandler. I have

UseDefaultCredentials = true 

and I tried to install

 Credentials = CredentialCache.DefaultNetworkCredentials 

but not one of them allows you to skip the API request.

Setting up the application pool to use my AD username and password allows all API requests to go through, and also call the API directly from Postman to correctly return data.

My guess is that the IIS AppPool [Pool Name] is forwarded in the request, and the proper credentials are never passed. In any case, this does not make the API insecure (for example, only a couple of domain groups should have access to it)?

An example of the call I make in the API from an 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; } } 
0
source share
3 answers

You can learn how to impersonate an authenticated user (Windows) on this GitHub talk page: https://github.com/aspnet/Home/issues/1805

ilanc has a really nice demo with reference to the bottom.

0
source

Without additional information, it is difficult to say for sure, but the problem is most likely related to the verification of two-house authentication.

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

When I needed to complete a similar task, I was unable to get HttpClient to work. I tried a number of suggested solutions on this issue. How do I get HttpClient to pass credentials along with the request? . Although it was informative - in particular, this part of BlackSpy's answer explains why:

What you are trying to do is force NTLM to redirect the identifier to the next server, which it cannot do - it can only perform an impersonation that gives you access to local resources.

As a result, I used WebClient (with the required .NET platform for targeting) with something like this in an MVC application (in this case, downloading the file from the web api):

 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 aim at the full structure does not allow this to be a .NET Core solution, but it looks like it has been added since.

Add WebClient to the new System.Net.WebClient contract

This PR port is System.Net.WebClient for corefx. The code is mostly taken from the desktop and then cleaned up a bit stylistically. The only basic code rewriting was removing hundreds of lines of complex code based on the APM callback and replacing it with several basic asynchronous methods. There is still a lot of cleaning that can be done, but functionally enough.

+3
source

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

+1
source

Source: https://habr.com/ru/post/1264894/


All Articles