C# HttpClient authorization header removed after send to server

4k Views Asked by At

I wanna send request to external API through the HttpClient from my own API in c#. I am using dot net 5 and basic authentication. Here is my code:

var client = new HttpClient 
{
    BaseAddress = new Uri(baseUrl)
};

HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Put, "apiUrl");

client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

var param = JsonConvert.SerializeObject(new
{
   param1="",
   param2=""
});

requestMessage.Content = new StringContent(param, Encoding.UTF8, "application/json");
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Basic",
     Convert.ToBase64String(Encoding.ASCII.GetBytes($"{user}:{pass}")));

HttpResponseMessage response = await client.SendAsync(requestMessage);

Usually, I send http request like this. but now I have some problem.

After line HttpResponseMessage response = await client.SendAsync(requestMessage); authorization header removed from my request header and I got UnAuthorized http error.

I know that when redirection occurs, authorization header removed for security reason. Also I'm not sure about redirect in external API.

I add the HttpClientHandler with AllowAutoRedirect = false to my HttpClient

var handler = new HttpClientHandler()
{
    AllowAutoRedirect = false,
};
var client = new HttpClient (handler)
{
    BaseAddress = new Uri(baseUrl)
};

Now I got Redirect error 301(Permanently moved).

I decided to test the code in Postman. By default, when I call API in Postman, I got http error 405 method not allowed and error detail like this:

{ "detail": "Method "GET" not allowed."}

External API method is PUT. but here I got GET Error. I tried many options in postman and finally I find the option in Postman: Follow original http method

When I toggle it on, external API work's properly. Also I test it with Insomnia and it's work properly.

Does it related to my code or dot net 5 or what other thing in my code or it's related to external API?

If it's related to my code, How can I solve the error?

If error related to external API, why Postman and Insomnia response is ok?

External API has Core Policy for specific domain and I send request from other domain. All I Know is that the CORS policy applied in browser. not in Postman, Insomnia or C# Code. What about CORS? Does it related to CORS? if Yes, what shall I do?

I will be grateful for your answer.

Update

I detect WWW-Authenticate: JWT realm="api" in the response header. What exactly is it? and what shall I do?

3

There are 3 best solutions below

2
Aliasghar Ahmadpour On BEST ANSWER

I find out the problem. It's really Ridiculous. When I use URL like www.abc.com/api/something the request gets 301 error and postman sends another request like www.abc.com/api/something/. The difference is just / at the end of request. I tried new URL in postman and first request got ok. Also I tried URL in my C# code and again its ok. But i could not understand why.

Thanks a lot dear @pharaz-fadaei

1
Darshani Jayasekara On

Since you see WWW-Authenticate: JWT realm="api" header, the external API is required a JWT token authentication, not basic authentication. I think first you might need to check external api's documentation.

6
Pharaz Fadaei On

You are right about the removal of authorization headers after redirects. But keep in mind that this behavior is part of the design of the HttpClient in C#. Postman and Insomnia may have different mechanisms to send the authorization headers on each consecutive request that is caused by redirects. The option that you enabled in Postman will make it use the original HTTP method you specified (PUT) as the HTTP method to send further requests based on the redirect messages (Postman uses GET method by default on requests instructed by redirect messages).

The fact that you see a 301 shows that a redirection is required. You can check Location header value in response.Headers to see the real location and send your requests with the authorization headers to that endpoint directly. If I were you I wouldn't use the new location directly because the original endpoint is what you were given by the authors of the API. Instead I would programmatically send the request to the original endpoint and resend the request on 301 codes to the new Location (use PUT method due to the behavior of Postman) until you get the result. This answer can give you some ideas: https://stackoverflow.com/a/42566541/1539231