dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.34k stars 4.74k forks source link

WebClient Negotiate DefaultCredentials not handled on redirect #34967

Open Martin11175 opened 4 years ago

Martin11175 commented 4 years ago

Hi all,

I seem to be running into an issue with .NET Core 3.1 not negotiating NTLM credentials on receiving a redirect. Using .NET Framework 4.5.1 (recorded in wireshark): image

Whereas in .NET Core 3.1: image

In both cases, the code is as follows:

using (var client = new System.Net.WebClient())
{
    client.Credentials = CredentialCache.DefaultCredentials;
    using (var response = client.OpenRead(URL))
    {
        // Process results
    }
}

If we replace the URL with the host the original request is redirected to though, the negotiate handshake goes off properly and the request succeeds in both instances. Is there a new flag we're missing somewhere, or is this a bug in .NET Core as I've seen similar issues with WebClient such as #17545 during my investigation (as we also enable Kerberos and NTLM).

Thanks for your help and please don't hesitate to reach out if we can provide any further information,

Martin

ghost commented 4 years ago

Tagging subscribers to this area: @dotnet/ncl Notify danmosemsft if you want to be subscribed.

davidsh commented 4 years ago

In general, credentials are dropped during redirects. That is done for security reasons. So, it is by-design.

But if you want to preserve credentials during a redirect, you can use a CredentialCache object and store the default credentials against a specific uri.

var cache = new CredentialCache();
cache.Add(new Uri("http://example.com"), "Negotiate", CredentialCache.DefaultCredentials);
client.Credentials = cache;
davidsh commented 4 years ago

On a further note, I will say that the behavior difference between .NET Framework and .NET Core probably still needs to be investigated/fixed. .NET Framework would remove credentials during redirects but only if redirecting to a different hostname:port in the Uri. For redirections within the same 'authority' portion of the Uri, it would preserve credentials.

.NET Core, however, seems to drop credentials on any redirect regardless of where the destination uri is. That is probably an app-compat difference that needs to be addressed.

karelz commented 4 years ago

Triage: We should likely fix that in 5.0 to make migration from .NET Framework easier.

karelz commented 4 years ago

Triage: Only 1 customer, there is workaround - handle the redirect yourself. Sadly, not enough time to fix it in 5.0, moving to Future.