I'm using the C# class HttpClient to make requests to a RESTful API. Are these requests secure by virtue of using an HTTPS URI? Or should I be doing more in the code to make sure the requests are secure?
Here is some sample code:
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("https://www.example.com");
client.DefaultRequestHeaders.Add("custom-header-1", "value-1");
client.DefaultRequestHeaders.Add("custom-header-2", "value-2");
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue(type, credentials);
HttpResponseMessage response = client.PostAsync(URLParameters, content).Result;
return response.Content.ReadAsStringAsync().Result;
I've read some material online with conflicting ideas:
Some people say that the URL being HTTPS is good enough.
Others say you have to manually take care of certificates in the code.
I'm confused as to which school of though is correct.
Related
I really have no idea about the issue here.
I have a DLL to send requests to an HTTPS server and get response with below C# code
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
string result = await response.Content.ReadAsStringAsync();
The DLL is with a standard interface. If this is called from my C# application, I got an error when read string from the response, sayiny "input string was not in a correct format". But if the URL is HTTP (not HTTPS) or it is called from a standard commercial application, it works.
Any help here is highly appreciated.
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:
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?
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
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
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.
I am trying to make a GET request to a RESTful service but the .NET HttpClient is receiving a timeout, but via Postman this returns an expected response (an error response, since I'm not yet "logged in") within seconds.
What I've tried:
I have checked the URLs are the same and they are.
I thought perhaps Postman's automagical headers are the issue, but after setting these in the HttpClient I still receive a timeout.
If I increase the timeout on the HttpClient I still get a timeout from the server ((504) Gateway Timeout).
Client = new HttpClient(new HttpClientHandler()
{
AutomaticDecompression = System.Net.DecompressionMethods.GZip
});
var objTask = Client.GetStringAsync(objUrl);
objTask.Wait();
strResponse = objTask.Result;
strResponse = Client.GetStringAsync(objUrl).Result;
Why am I receiving a timeout via HttpClient?
Note:
Our WebApi is calling our WCF Service, which in turn is calling the 3rd party RESTful service via HttpClient---for security reasons I can't call the 3rd party API directly from our WebApi controller. The website is based on the .NET 4.0 Framework.
With lots of help from #jdweng and #gunr2171, I've realised the issue was due to the proxy stored in the App.Config on the self-hosted WCF Services. If I commented this out, I wouldn't get a time-out issue.
The HttpClient constructor can take in a HttpClientHandler, which has a Proxy property where you can bypass the local proxy as so:
return new HttpClient(new HttpClientHandler()
{
AutomaticDecompression = System.Net.DecompressionMethods.GZip,
Proxy = new WebProxy()
{
BypassProxyOnLocal = true
}
})
{
BaseAddress = new Uri("https:\\my.service")
};
I am trying to use a Rest API from outside my company's domain. My problem is when I run the POST request within Postman or an Angular application it works fine. But when I send the same payload within a winforms c# application, I get Access Forbidden. You have browsed from an unrecognized IP address. The proxy therefore denied access to this site.
I thought the problem was with the payload itself, so I copied the same JSON string, sent it via postman and It worked. So I thought perhaps the issue is with the server itself, so I ran other GET requests to the same server and they worked. I tried sending an empty string to the POST request and it worked, tried an empty object and get FORBIDDEN REQUEST. The same code, I ran it from my personal computer and it worked.
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", sToken);
StringContent sRequestContent = new StringContent(requestPayload, Encoding.UTF8, "application/json");sRequestContent).Result;
var result = client.PostAsync(new Uri(sUrl), sRequestContent).Result;
return result.Content.ReadAsStringAsync().Result;
PS:
requestPayload is a JSON string.
I'm using System.Net.Http HttpClient to call Github's rest API.
About 5 out of every 10 requests I make with the HTTP client generated below respond with "401 Unauthorized". I put the same URL and headers in postman and never get any "401 Unauthorized" responses. Clearly, my problem is on the client side.
A reasonable search returned a lot of different advice. The most common was to use an HttpHandler, or webrequest, but it's still not clear why some requests fail. My best guesses were that Github occasionally redirects and the client doesn't handle it well. I saw some references about caching credentials, but those examples all showed "NetworkCredential" object, and but for OAuth we just put the bearer token in the header as shown below, so I'm not sure if that applies to my case.
Can anyone explain the cause of the issue?
public static HttpClient GetClient(string bearerToken)
{
HttpClient client = new HttpClient();
client.BaseAddress = _githubApiUri;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(_mediaTypeWithQualityHeaderValue));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", bearerToken);
client.DefaultRequestHeaders.Add("User-Agent", "System.Net.Http Agent");
return client;
}
It turned out that my clock was 15 seconds fast, making the tokens I was generating invalid because they were "from the future" from Githubs perspective. So, if I paused with a breakpoint, and happened to wait 15 seconds, or more, it would work.