0

Note: This is not a duplicate of this question. I have already read that question and its answers.

Approach 1

var client = new HttpClient() { BaseAddress = new Uri("https://myurl") };
var authenticationString = "username:password"; // Obviously this will be actual username & pass
var base64EncodedAuthenticationString = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(authenticationString));
client.DefaultRequestHeaders.Add("Basic", base64EncodedAuthenticationString);
HttpResponseMessage responseToken = client.GetAsync("/customer/151375").Result;
string data = responseToken.Content.ReadAsStringAsync().Result;

Above approach does not work and, if it helps, when I inspect the response.RequestMessage.RequestUri it is different from https://myurl/customer/151375. This approach returns some HTML.

Approach 2

HttpClientHandler httpClientHandler = new HttpClientHandler()
{
    Credentials = new NetworkCredential("username", "password")
};

var client = new HttpClient(httpClientHandler);
HttpResponseMessage response =
client.GetAsync("https://myurl/customer/151375/contacts").Result;
string data = response.Content.ReadAsStringAsync().Result;

Approach 2 works but Approach 1 does not work. To me both requests are the same but clearly they are not.

What are the differences between above 2 approaches?

Why does only Apporach 2 work?

CodingYoshi
  • 25,467
  • 4
  • 62
  • 64
  • 1
    `DefaultRequestHeaders.Add("Basic", base64EncodedAuthenticationString)` adds a header `Basic: ABC123`. But the correct header should would be `Authorization: Basic ABC123` – thehennyy Nov 11 '22 at 13:27
  • @thehennyy good eye. also `$"username:password"` should it be `$"{username}:{password}"` ? – Joe_DM Nov 11 '22 at 13:31
  • @Joe_DM Sorry the strings were actual username and password, not variables. `$` was just there but removed it. – CodingYoshi Nov 11 '22 at 13:39
  • @thehennyy Same issue, does not work. – CodingYoshi Nov 11 '22 at 13:40
  • Can you see the headers being set when `NetworkCredential` is used? are you sure it's using a Basic auth and not NTLM or something different – Joe_DM Nov 11 '22 at 13:43
  • @Joe_DM I checked the headers for the 2nd approach and there is nothing for authorization. I searched for that online first, before posting question, to find out how `NetworkCredential` gets transported in HTTP & HTTPS but I found nothing. – CodingYoshi Nov 11 '22 at 13:47
  • I did a test and I see the initial request has no headers. Could there be other requests going back and forward such as a challenge and then a response. – Joe_DM Nov 11 '22 at 13:49
  • I found this link https://weblog.west-wind.com/posts/2021/Nov/27/NTLM-Windows-Authentication-Authentication-with-HttpClient which indicates that "it needs to be challenged before sending credentials". maybe that is what is going on here. then from the challenge it can decide which format to provide the credential. e.g. Negotiate, NTLM, Basic, etc – Joe_DM Nov 11 '22 at 13:56
  • @Joe_DM What do you mean the initial request has no headers? I see it when I look at `response.RequestMessage.Headers`. The HTML returned, I saved it and looked at it and it shows a login form. – CodingYoshi Nov 11 '22 at 13:56
  • This is what I see in a test request when I try. https://i.imgur.com/5YYWdjU.png – Joe_DM Nov 11 '22 at 13:58
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/249518/discussion-between-codingyoshi-and-joe-dm). – CodingYoshi Nov 11 '22 at 14:00

1 Answers1

0

If you want to use Authorization headers, you need to name it properly. Header has a name and value. Authentication headers have name "Authorization" and value depends on Authorization type you want to use. You are using "Basic" Authorization scheme. First word in Authorization header value is name of used scheme. Most used are probably "Basic" and "Bearer" Authorization headers. In your first approach use this:

client.DefaultRequestHeaders.Add("Authorization",$"Basic {base64EncodedAuthenticationString}");