Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you use Basic Authentication with System.Net.Http.HttpClient?

Tags:

I'm trying to implement a rest client in c# .net core that needs to first do Basic Authentication, then leverage a Bearer token in subsequent requests.

When I try to do Basic Authentication in combination with client.PostAsync with a FormUrlEncodedContent object, I'm getting an exception:

System.InvalidOperationException occurred in System.Net.Http.dll: 'Misused header name. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects.' 
//setup reusable http client HttpClient client = new HttpClient(); Uri baseUri = new Uri(url); client.BaseAddress = baseUri; client.DefaultRequestHeaders.Clear(); client.DefaultRequestHeaders.ConnectionClose = true;  //Post body content var values = new List<KeyValuePair<string,string>>(); values.Add(new KeyValuePair<string, string>("grant_type", "client_credentials"));  var content = new FormUrlEncodedContent(values);  //Basic Authentication var authenticationString = $"{clientId}:{clientSecret}"; var base64EncodedAuthenticationString = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(authenticationString)); content.Headers.Add("Authorization", $"Basic {base64EncodedAuthenticationString}");  //make the request var task = client.PostAsync("/oauth2/token",content); var response = task.Result; response.EnsureSuccessStatusCode(); string responseBody = response.Content.ReadAsStringAsync().Result; Console.WriteLine(responseBody); 
Exception has occurred: CLR/System.InvalidOperationException An unhandled exception of type 'System.InvalidOperationException' occurred in System.Net.Http.dll: 'Misused header name. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects.'    at System.Net.Http.Headers.HttpHeaders.GetHeaderDescriptor(String name)    at System.Net.Http.Headers.HttpHeaders.Add(String name, String value) 
like image 633
ScArcher2 Avatar asked Sep 19 '19 15:09

ScArcher2


People also ask

What is HTTP basic authentication and how it works?

HTTP basic authentication is a simple challenge and response mechanism with which a server can request authentication information (a user ID and password) from a client. The client passes the authentication information to the server in an Authorization header. The authentication information is in base-64 encoding.


2 Answers

It looks like you can't use PostAsync and have access to mess with the Headers for authentication. I had to use an HttpRequestMessage and SendAsync.

//setup reusable http client HttpClient client = new HttpClient(); Uri baseUri = new Uri(url); client.BaseAddress = baseUri; client.DefaultRequestHeaders.Clear(); client.DefaultRequestHeaders.ConnectionClose = true;  //Post body content var values = new List<KeyValuePair<string, string>>(); values.Add(new KeyValuePair<string, string>("grant_type", "client_credentials")); var content = new FormUrlEncodedContent(values);  var authenticationString = $"{clientId}:{clientSecret}"; var base64EncodedAuthenticationString = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(authenticationString));  var requestMessage = new HttpRequestMessage(HttpMethod.Post, "/oauth2/token"); requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Basic", base64EncodedAuthenticationString); requestMessage.Content = content;  //make the request var task = client.SendAsync(requestMessage); var response = task.Result; response.EnsureSuccessStatusCode(); string responseBody = response.Content.ReadAsStringAsync().Result; Console.WriteLine(responseBody); 
like image 140
ScArcher2 Avatar answered Oct 04 '22 15:10

ScArcher2


Don't encode the whole authentication string - encode the "Username:Password" expression and append the result to the "Basic " prefix.

var authenticationString = $"{clientId}:{clientSecret}"; var base64EncodedAuthenticationString = Convert.ToBase64String(System.Text.ASCIIEncoding.UTF8.GetBytes(authenticationString)); content.Headers.Add("Authorization", "Basic " + base64EncodedAuthenticationString); 

Also, consider using just ASCII encoding - the UTF8 may not be understood by the server unless you add a charset declaration to the header.

Wikipedia seems to cover this quite well.

like image 41
Neil Moss Avatar answered Oct 04 '22 13:10

Neil Moss