runtime: NTLM authentication sometimes broken by multiple WWW-Authenticate headers
This issue has been split off from dotnet/runtime#17545, which turned out to be a problem in the tool being used to observe network traffic. Other users saw similar results, but under different conditions and not caused by the testing tool. That issue will be tracked here to clearly separate the two issues.
The issue tracked here occurs with the following code, targeting .NET Core 2.0:
var creds = new CredentialCache();
creds.Add(new Uri(addy),"NTLM",new NetworkCredential(Username,Password));
var handler = new HttpClientHandler
{
Credentials = creds,
};
HttpClient client = new HttpClient(handler);
client.BaseAddress = new Uri(addy);
var response = await client.GetAsync("api/myresource");
In Windows, the server receives the following headers, but does not initiate the NTLM handshake:
HTTP/1.1 401 Unauthorized
Content-Type: text/html
Server: Microsoft-IIS/8.5
WWW-Authenticate: NTLM
WWW-Authenticate: Negotiate
X-Powered-By: ASP.NET
Date: Thu, 01 Mar 2018 22:17:34 GMT
Content-Length: 1293
@dbrownxc, can you provide more information on the situation in which you were able to reproduce this issue? It would be good to have full logs for the unsuccessful authentication attempt.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Comments: 21 (10 by maintainers)
Commits related to this issue
- Check available credentials when choosing authentication scheme (#28105) When choosing what authentication scheme to use, WinHttpHandler picks the most secure scheme supported by the server. When the... — committed to dotnet/corefx by rmkerr 6 years ago
- Check available credentials when choosing authentication scheme (#28105) When choosing what authentication scheme to use, WinHttpHandler picks the most secure scheme supported by the server. When the... — committed to ericstj/corefx by rmkerr 6 years ago
- Fixing the return type of the ArmBase.ReverseElementBits methods in the PlatformNotSupported file (#27672) Signed-off-by: dotnet-bot <dotnet-bot@microsoft.com> — committed to Dotnet-GitSync-Bot/corefx by tannergooding 5 years ago
- Fixing the return type of the ArmBase.ReverseElementBits methods in the PlatformNotSupported file (#27672) Signed-off-by: dotnet-bot <dotnet-bot@microsoft.com> — committed to dotnet/corefx by tannergooding 5 years ago
I think I’ve tracked this issue down. Here are the conditions under which it will repro:
In the conditions we see here, the user provides NTLM credentials, but the server supports both NTLM and Negotiate (which is considered more secure).
WinHttpHandler
erroneously chooses to attempt authentication with Negotiate. When we later detect that there are no credentials in the cache that support Negotiate, we close the connection.This happens because the code we use to choose the authentication scheme only considers the schemes supported by the server, and not those supported by the client. If the we don’t have credentials for the most secure protocol supported by the server, we will fail the authentication attempt.
You can see the code that chooses the authentication scheme below. The parameter
supportedSchemes
indicates the schemes supported by the server. https://github.com/dotnet/corefx/blob/1de2b37722e0987eaea07bd8e23a3d78d4ea36b2/src/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpAuthHelper.cs#L374-L385 The fix for this is simple, and I have a tentative version working. I’m adding some additional tests now, and if all goes well I’ll try to get the PR out this afternoon.(1) Our implementation ranks schemes in the following order: Negotiate, NTLM, Digest, Basic
Or you can use 2.1 (currently Preview2) where it is fixed.
@rmadisonhaynie For us, it is a matter of switching between NTLM and Negotiate depending on environment.
For now, what we are doing is setting this in configuration. Using the new configuration classes, we just set up a development configuration (appSettings) that works for Windows and a release configuration that works for Linux (environment variable override works here).
Yep! Thanks for getting around to sending out the repro @dbrownxc – it makes things way more manageable on our end.