How does the System.Net.Http.HttpClient select authentication type?

Las*_*sen 6 .net c# dotnet-httpclient .net-core

Let's say I new up the HttpClient and send off a request to a protected endpoint like this:

var httpClient = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "url");
var response = await httpClient.SendAsync(request);
Run Code Online (Sandbox Code Playgroud)

I then get a response with the following headers:

HTTP/1.1 401 Unauthorized
Content-Type: text/html
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
WWW-Authenticate: Basic
Date ...
Run Code Online (Sandbox Code Playgroud)

From the response headers, I see that I have three different options to authenticate with the server (Negotiate, NTLM, Basic). I then update my code to this:

var httpClientHandler = new HttpClientHandler
{
    Credentials = new NetworkCredential
    {
        UserName = "username",
        Password = "password"
    }
};
var httpClient = new HttpClient(httpClientHandler);
var request = new HttpRequestMessage(HttpMethod.Get, "url");
var response = await httpClient.SendAsync(request);
Run Code Online (Sandbox Code Playgroud)

I execute my program again, and this time I get a 200 OK in return. All fine.

If I inspect the request with fiddler, I see that the HttpClient decided to use "Negotiate" as the authentication method.

Now, my question is: how does the HttpClient decide which authentication type to apply? Does it have a precedence for some authentication types over others?

The docs on NetworkCredential states that:

The NetworkCredential class is a base class that supplies credentials in password-based authentication schemes such as basic, digest, NTLM, and Kerberos.

... so I know the credentials I provide could have been applied for all three authentication types, but I have not been able to figure out how / why it selects a specific authentication type over another.

Any insight into this is greatly appreciated, thanks in advance!

Osc*_*rez 0

您可以使用GetCredential方法,它将为您提供身份验证类型的凭据。有点奇怪但有效:

var httpClientHandler = new HttpClientHandler
{
    Credentials = new NetworkCredential
    {
        UserName = "username",
        Password = "password"       
    }.GetCredential("*", 80, "Basic") // Substitute * and 80 with url and port if possible
};
var httpClient = new HttpClient(httpClientHandler);
var request = new HttpRequestMessage(HttpMethod.Get, "url");
var response = await httpClient.SendAsync(request);
Run Code Online (Sandbox Code Playgroud)

评论澄清后

当您有多种身份验证类型时,客户端必须使用可用的最强方法(但有时这很难说)。

来源: HTTP 身份验证 - WWW-Authenticate 标头 - 多个领域