6

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 Answers3

7

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

4

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

Pharaz Fadaei
  • 1,605
  • 3
  • 17
  • 28
  • You are right, but the location does no changed and response.location is same URL as initial URL which i send my request to. – Aliasghar Ahmadpour Jul 17 '21 at 07:32
  • Also I talked to API provider, they said there's no redirect in destination API. is there any other reason for redirect error? – Aliasghar Ahmadpour Jul 17 '21 at 07:36
  • 1
    @AliasgharAhmadpour I think you can verify if any redirects happen by looking at the console logs in Postman. There should be a button in the bottom-left corner of Postman to open the console. Send a request that works and check the console to see how many requests are being sent. – Pharaz Fadaei Jul 17 '21 at 07:41
  • Thank you @pharaz-fadaei It's a good clue. every time I send request in postman, two request executed. first request gets 301 error and another request executed successfully. main diff between first and second is that the referrer and host added in second request header Is it the problem? I mean does problem relate to referrer? – Aliasghar Ahmadpour Jul 17 '21 at 08:04
  • @AliasgharAhmadpour are you sure those are the only differences? The `Host` header will be set by Postman in every request, so in this case the only difference will be the `Referrer` header. Try setting `Referrer` in your first request and see if that works. I would be surprised if this is the solution! – Pharaz Fadaei Jul 17 '21 at 08:09
  • 1
    Dear @pharaz-fadaei the bounty belongs to you. Your good clue is solved my problem – Aliasghar Ahmadpour Jul 17 '21 at 08:55
1

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.

Darshani Jayasekara
  • 561
  • 1
  • 4
  • 14