HttpClient Authorization Header Invalid Format - c#

When I try to make a GET request with the address and Authorization value below, I have no problems.
Address: http://example.com/xyz.svc/branches/?latitude=0&longitude=0&range=20000
Header Key: Authorization
Value: example;foo
When I try it with HttpCLient I get format invalid error for the authorization header value
This is how I tried
HttpClient client = new HttpClient();
string latitude = "0";
string longitude = "0";
string range = "2000";
string uri = "/xyz.svc/branches/?latitude=0&longitude=0&range=20000;
string value = "foo";
client.BaseAddress = new Uri("http://example.com");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("Authorization", String.Format("example;{0}", value));
HttpResponseMessage response = await client.GetAsync(uri);
var responseJson = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseJson);
What am I doing wrong?

Normally that authorization header has a format as {scheme} {token} which is what it is trying to validate with your current code.
Some servers can be configured to accept different formats. To avoid the client validating the standard format use TryAddWithoutValidation
client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", String.Format("example;{0}", value));
which based on your example would have the following request headers
Accept application/json
Authorization example;foo

Related

Is it possible to generate headers automatically with HttpClient / RestSharp?

At the moment I am using the following RestSharp request to get a website's content:
var client = new RestClient(productLink);
var request = new RestRequest(Method.GET);
request.AddHeader("Cookie", "insert-cookie-content");
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
I have tried converting it into HttpClient as i will need to use the AllowRedirect property later:
var client = new HttpClient();
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("Cookie", "insert-cookie-content");
var response = await client.GetAsync(productUrl);
Console.WriteLine(response);
The URL I am trying to get a response from is: https://www.nike.com/sg/launch/t/air-max-90-orange-duck-camo
My first problem is that the HttpClient request is giving me 403 Errors whereas the RestClient request was working fine. How can I fix this?
My second problem is that the cookie expires after a couple of uses, and I have to manually get a new one from postman and insert it. Is there anyway for the request to generate its own cookie?
Here is the two fiddler responses compared: https://imgur.com/a/bZo7d9F
In case of HttpClient if you want to pass the Cookies manually through the DefaultRequestHeaders then you have to tell this to the HttpClient to do NOT use CookieContainer. You have to use HttpClientHandler's UseCookie flag to indicate it.
var client = new HttpClient(new HttpClientHandler { UseCookies = false });
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("Cookie", "insert-cookie-content");
var response = await client.GetAsync(productUrl);
Console.WriteLine(response);

Why is fiddler showing a 0 for the http post body? Does this look correct?

Trying to simply post a string to a web api to make sure it works and the json string doesn't seem to be there even though I can see it in the debugger.. Is there something obvious I am missing ?
RootObject ro = new RootObject();
ro.JobID = 9999;
var dataAsString = JsonConvert.SerializeObject(ro); //there is a json string here
var content = new StringContent(dataAsString);
var client = _clientFactory.CreateClient();
client.BaseAddress = new System.Uri("http://localhost:55816");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain"));
var response = await client.PostAsJsonAsync("/api/Jobs/", content);
{"Files":null,"JobID":9999,"ReadyForPublish":false,"ScheduledJobID":null}
With an HttpClient you can directly use the result of JsonConvert.SerializeObject(ro); as the second argument to the PostAsJsonAsync. No need to use the StringContent.

HTTPClient and JWT Authentication in C#

I'm having a hard time trying to use authorization in C# Winforms. My purpose is to access the API. I already get the access token but when I try to pass it to the header, it returns an error:
HTTP error 400.
My code:
using (var httpClient = new HttpClient())
{
var url = #"https://acerportal.com/v1/414232363/status/device/";
httpClient.BaseAddress = new Uri(url);
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", accessToken);
var response = await httpClient.GetStringAsync(url);
string checkResult = response.ToString();
MessageBox.Show(checkResult);
}
The header has to look a little different, the format is Authorization: <type> <credentials> - so it's like this for jwt:
httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
For an explanation, also see https://security.stackexchange.com/questions/108662/why-is-bearer-required-before-the-token-in-authorization-header-in-a-http-re
Hi already solve the problem by simply removing "Bearer" on the inputs.

RestSharp get full URL of a request

Is there a way to get the full url of a RestSharp request including its resource and querystring parameters?
I.E for this request:
RestClient client = new RestClient("http://www.some_domain.com");
RestRequest request = new RestRequest("some/resource", Method.GET);
request.AddParameter("some_param_name", "some_param_value", ParameterType.QueryString);
IRestResponse<ResponseData> response = client.Execute<ResponseData>(request);
I would like to get the full request URL:
http://www.some_domain.com/some/resource?some_param_name=some_param_value
To get the full URL use RestClient.BuildUri()
Specifically, in this example use client.BuildUri(request):
RestClient client = new RestClient("http://www.some_domain.com");
RestRequest request = new RestRequest("some/resource", Method.GET);
request.AddParameter("some_param_name", "some_param_value", ParameterType.QueryString);
IRestResponse<ResponseData> response = client.Execute<ResponseData>(request);
var fullUrl = client.BuildUri(request);
Well, it is pretty tricky.
To get the full requested URL use RestClient.Execute(request).ResponseUri to be sure it is the already sent request.
In this example:
RestClient client = new RestClient("http://www.some_domain.com");
RestRequest request = new RestRequest("some/resource", Method.GET);
request.AddParameter("some_param_name", "some_param_value", ParameterType.QueryString);
IRestResponse<ResponseData> response = client.Execute<ResponseData>(request);
Uri fullUrl = response.ResponseUri;
This code:
Console.WriteLine(string.Format("response URI: {0}", response.ResponseUri.ToString()));
returns:
response URI: http://www.some_domain.com/some/resource?some_param_name=some_param_value

HttpClient authentication header not getting sent

I'm trying to use an HttpClient for a third-party service that requires basic HTTP authentication. I am using the AuthenticationHeaderValue. Here is what I've come up with so far:
HttpRequestMessage<RequestType> request =
new HttpRequestMessage<RequestType>(
new RequestType("third-party-vendor-action"),
MediaTypeHeaderValue.Parse("application/xml"));
request.Headers.Authorization = new AuthenticationHeaderValue(
"Basic", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", "username", "password"))));
var task = client.PostAsync(Uri, request.Content);
ResponseType response = task.ContinueWith(
t =>
{
return t.Result.Content.ReadAsAsync<ResponseType>();
}).Unwrap().Result;
It looks like the POST action works fine, but I don't get back the data I expect. Through some trial and error, and ultimately using Fiddler to sniff the raw traffic, I discovered the authorization header isn't being sent.
I've seen this, but I think I've got the authentication scheme specified as a part of the AuthenticationHeaderValue constructor.
Is there something I've missed?
Your code looks like it should work - I remember running into a similar problem setting the Authorization headers and solved by doing a Headers.Add() instead of setting it:
request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "username", "password"))));
UPDATE:
It looks like when you do a request.Content, not all headers are being reflected in the content object. You can see this by inspecting request.Headers vs request.Content.Headers. One thing you might want to try is to use SendAsync instead of PostAsync. For example:
HttpRequestMessage<RequestType> request =
new HttpRequestMessage<RequestType>(
new RequestType("third-party-vendor-action"),
MediaTypeHeaderValue.Parse("application/xml"));
request.Headers.Authorization =
new AuthenticationHeaderValue(
"Basic",
Convert.ToBase64String(
System.Text.ASCIIEncoding.ASCII.GetBytes(
string.Format("{0}:{1}", "username", "password"))));
request.Method = HttpMethod.Post;
request.RequestUri = Uri;
var task = client.SendAsync(request);
ResponseType response = task.ContinueWith(
t =>
{ return t.Result.Content.ReadAsAsync<ResponseType>(); })
.Unwrap().Result;
This would also work and you wouldn't have to deal with the base64 string conversions:
var handler = new HttpClientHandler();
handler.Credentials = new System.Net.NetworkCredential("username", "password");
var client = new HttpClient(handler);
...
Try setting the header on the client:
DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(String.Format("{0}:{1}", userName, password))));
This works for me.
Also, consider that Redirect-Handler will clear the Authorization header if your request gets redirected.
So if you call an HTTP endpoint and it redirected to the HTTPS one, you will lose your authorization header.
request.Headers.Authorization = null;
Framework: .NET v6.0
Actually your problem is with PostAsync- you should use SendAsync. In your code - client.PostAsync(Uri, request.Content); sends only the content the request message headers are not included.
The proper way is:
HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = content
};
message.Headers.Authorization = new AuthenticationHeaderValue("Basic", credentials);
httpClient.SendAsync(message);

Categories