26

I’ve got a situation with a large internal corporate web based application running ASP.NET 3.5 on IIS6 generating 401 “Unauthorised” responses followed by 200 “Ok” responses (as profiled by Fiddler). I’m aware of why this happening (integrated auth forcing the browser to resend credentials) but I’m looking for some thoughts on how to minimise or eradicate the situation. The application in question is running in the WAN with some users experiencing latency of up to 250ms so forcing a subsequent request can have a noticeable impact on page load time, particularly when there are a number of cascading drop down lists on the pages making.

The users of the application are internal within a managed desktop environment so mechanisms to force the browser to send credentials on the first request (is this even possible?) could be possible from a deployment perspective. This would work for pages requiring the user’s identity but for resources not requiring authentication (WebResource.axd, ScriptResource.axd and some custom web services), allowing anonymous auth would be possible. I’ve looked at defining this on a per location basis in the web.config but the results were mixed (still a number of 401 responses).

I’d appreciate any guidance on a “best practice” for dealing with this situation. There are a lot of resources out there identifying the problem but none that I’ve found providing a feasible solution.

Thanks!

Edit: Resources not requiring authentication (i.e. web services used for cascading drop down lists) can be requested anonymously through adding a location entry to the web config but I'm yet to find an answer for authenticated resources.

Troy Hunt
  • 20,345
  • 13
  • 96
  • 151

5 Answers5

18

Unfortunately this is an artifact of the HTTP NTLM authentication scheme.

In short, the browser (Internet Explorer or otherwise) doesn't know that it needs to authenticate at all until it gets bounced with a 401 response containing a WWW-Authenticate response header.

In the case of WWW-Authenticate: NTLM -- annoyingly enough -- it requires two 401 responses on a single persistent connection to complete, and this process must be repeated once the HTTP persistent connection is closed. So even if you were able to get the browser to initiate a request blindly attempting NTLM, at least one 401 response cannot be removed from the transaction.

I think your best bet would be to maximize the amount of time that persistent connections are left open when idle.

Jeffrey Hantin
  • 35,734
  • 7
  • 75
  • 94
  • Check out IIS Settings. http://msdn.microsoft.com/en-us/library/aa347472.aspx You can play with these settings to reduce 401 requests.. Be careful though about your choices.. AuthPersistNonNTLM, authPersistSingleRequest – batspy Jun 14 '14 at 05:11
3

CSCRIPT.EXE c:\inetpub\adminscripts\ADSUTIL.VBS SET W3SVC/AuthPersistSingleRequest FALSE

Will reduce the amount of 401's significantly.

Rob Fuller
  • 514
  • 2
  • 7
0

TL;DR I put HTTP header information in HTTP body

My example is in Angular, but any TypeScript/JavaScript (framework) might have the same issue.

When doing a HTTP post call to my backend API, which requires headers with the logged in user information, I added my HTTP headers where my HTTP body should be and the headers were empty.

PROBLEM

  markInstructionAsCompleted(visitScheduleId: string, instructionId: number) {
    return this.http.post(`${environment.apiUrl}/VisitInstructions/schedule/${visitScheduleId}/done/${instructionId}`, this.getHeaderWithAuthorization());
  }

SOLUTION, notice that there's an added second argument to the HTTP post call, which is null

  markInstructionAsCompleted(visitScheduleId: string, instructionId: number) {
    return this.http.post(`${environment.apiUrl}/VisitInstructions/schedule/${visitScheduleId}/done/${instructionId}`, null, this.getHeaderWithAuthorization());
  }
Ruben Szekér
  • 1,065
  • 1
  • 10
  • 21
0

I believe you can convince Firefox to automatically send NTLM credentials to a whitelisted set of domains via "about:config" settings - use the "network.automatic-ntlm-auth.trusted-uris" setting. I haven't tried this myself though. I'm not sure there's any equivalent for Internet Explorer.

Unfortunately if you're using something else like Kerberos there does not seem to be a way to avoid the 401.

bhollis
  • 4,624
  • 2
  • 28
  • 32
  • Thanks BRH, unfortunately the dependancy is on IE6 and 7. – Troy Hunt Mar 29 '09 at 08:27
  • 2
    Setting the `network.automatic-ntlm-auth.trusted-uris` as you describe does allow Firefox to authenticate without asking the user for the domain credentials, but it does not solve the "problem" of the 401-401-200 pattern. That is part of NTLM authentication and will always occur, regardless of the browser settings. – hmqcnoesy Aug 21 '12 at 17:37
0

You may need to consider Forms Authentication if the 401-induced latency is too long. The users would have to explicitly log in, but just once. Then you could use a cookie or cookieless scheme and get a response on the first try.

I imagine that page load would be slow if you have cascading drop-downs and your initial page load populates one value that causes a POST to get the next list, set that value, another POST to get the next list again, and so on. If this is the situation, perhaps you need to populate all those drop-downs on the first round-trip rather than waiting for POST responses.

JJO
  • 744
  • 1
  • 6
  • 11