Emulating Curl --user --insecure in c# - c#

I have the following Curl Call that works.
curl --insecure --user user#applicationname:password "https://someURL"
I cannot for the life of me get HttpWebRequest to emulate this.
Currently I am trying
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://someURL);
httpWebRequest.ContentType = "application/json";
httpWebRequest.Accept = "*/*";
httpWebRequest.Method = "POST";
httpWebRequest.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes("USER#Account:Password"));
I am getting the error Authentication failed because the remote party has closed the transport stream
I am guessing it has to do with the curl command having the insecure option but I cannot for the life of me see how to do this in the request.
Do to network restrictions/policies I cannot download restSharp or any other 3rd party libraries...

Add this line before doing the request
System.Net.ServicePointManager.ServerCertificateValidationCallback = (obj, X509certificate, chain, errors) => true;

I ended up using HttpClient instead. In combination with using the info obtained from #Alberto Monteiro above, I was able to get the my code to work as expected.
string url = Request.Form["Url"];
using (var client = new HttpClient())
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11;
ServicePointManager.ServerCertificateValidationCallback = (obj, x509Certificate, chain, errors) => true;
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("text/xml"));
var byteArray = Encoding.ASCII.GetBytes(Request.Form["User"] + "#ACCOUNT:" + Request.Form["Pass"]);
var header = new AuthenticationHeaderValue(
"Basic", Convert.ToBase64String(byteArray));
client.DefaultRequestHeaders.Authorization = header;
var response = client.GetAsync(url).Result;
HttpContent content = response.Content;
string result = content.ReadAsStringAsync().Result;
}

Related

UWP App fails to post to a web service as multipart/form-data with digest authentication

When trying to post to a web service as multipart/form-data with digest authentication. It is failing with the following error 'System.Net.CredentialCache' is not supported for property 'Credentials'.
Using the below code to send credentials:
HttpWebRequest httpWebRequest = WebRequest.Create(requestUrl) asHttpWebRequest;
string formDataBoundary = String.Format("----------{0:N}", Guid.NewGuid());
string contentType = "multipart/form-data; boundary=" + formDataBoundary;
byte[] formData = GetMultipartFormData(parameters, formDataBoundary);
if (httpWebRequest == null)
{
thrownewNullReferenceException("request is not a http request");
}
// Set up the request properties.
httpWebRequest.Method = "POST";
httpWebRequest.ContentType = contentType;
httpWebRequest.CookieContainer = newCookieContainer();
var credentialCache = newCredentialCache();
credentialCache.Add(
newUri("http://someurl.com"), // request url's host
"Digest", // authentication type
newNetworkCredential(username, password) // credentials
);
httpWebRequest.Credentials = credentialCache;
We changed the services to use post with application/json instead and that solved it.
var response = await httpClient.PostAsync(requestUrl, new
StringContent(jsonString, Encoding.UTF8, "application/json"));

Windows-Universal https Post Xamarin Forms

I want to make a Json Post Request with my Windows Universal App.
I have it working in my Android and IOS.
public String DoServiceCall()
{
var request = (HttpWebRequest)WebRequest.Create(string.Format("{2}/{0}/{0}ServiceJson.svc/{1}", "Authentication", "Authenticate", "https://....."));
using (MemoryStream ms = new MemoryStream())
{
// create the request object
string requestString = JSONRequest;
byte[] requestData = Encoding.UTF8.GetBytes(requestString);
request.Method = "POST";
request.ContentType = "application/json; charset=UTF-8";
request.ContentLength = requestData.Length;
request.AllowAutoRedirect = false;
// add known cookies to request (needed for authentication)
CookieContainer requestCookies = new CookieContainer();
foreach (Cookie knownCookie in this._cookieCollection)
{
requestCookies.Add( knownCookie);
}
request.CookieContainer = requestCookies;
//For getting rid of the https Problem
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
using (Stream stream = request.GetRequestStream())
{
stream.Write(requestData, 0, requestData.Length);
}
// get response data
HttpWebResponse response = (HttpWebResponse) request.GetResponse();
string responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
return (responseString);
}
}
The Problem is that Windows Universal does not support.
request.ContentLength = requestData.Length;
request.AllowAutoRedirect = false;
requestCookies.Add( knownCookie); //with only one Argument
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
Neither does it support.
request.GetRequestStream())
(HttpWebResponse) request.GetResponse();
But that i could fix with async
await request.GetRequestStreamAsync())
(HttpWebResponse)await request.GetResponseAsync();
But without that 4 Lines i couldn´t get it working on Windows.
I just doesn´t get any Response.
Is there an Option to get it working on Windows 10 or is there an Working alternative.
So i finally found a solution.
Based on the Comment i tried the HttpClient.
But the Stanard Httpclient in the system namespace doesn`t support filter, which i need to get pass the SSL certificat problem.
Luckly in the Windows.Web.Http namespace, there is another HttpClient, which suppports filters.
The answer is the fully functional HttpClient Post Call.
public async void testcallwind()
{
List<HttpCookie> cookieCollection = new List<HttpCookie>();
HttpBaseProtocolFilter filter = new HttpBaseProtocolFilter();
HttpClient httpClient;
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);//Allow untrusted CA's
filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Expired);
// add known cookies to request (needed for authentication)
foreach (HttpCookie knownCookie in cookieCollection)
{
filter.CookieManager.SetCookie(knownCookie);
}
httpClient = new HttpClient(filter);
string resourceAddress = string.Format("https://...");
string requestString = "{\"request\":{\"CallerState\":null,...."}}";
byte[] requestData = Encoding.UTF8.GetBytes(requestString);
UnicodeEncoding en = new UnicodeEncoding();
IHttpContent content = new HttpStringContent(requestString, 0, "application/json");
Uri postBody = new Uri(resourceAddress);
var response = await httpClient.PostAsync(postBody, content);
httpClient.Dispose();
var test = response.Content;
}

C# https request always tunnel to server but Java only once

I'm converting JAVA program to C# that send https request to server. Here is my program that log in to server and then log-out from server.
var login_httpWebRequest = (HttpWebRequest)WebRequest.Create(m_base_url + "session/login");
login_httpWebRequest.ContentType = "application/json; charset=UTF-8";
var logout_httpWebRequest = (HttpWebRequest)WebRequest.Create(m_base_url + "session/logout");
logout_httpWebRequest.ContentType = "application/json; charset=UTF-8";
CookieContainer cookieJar = new CookieContainer();
login_httpWebRequest.CookieContainer = cookieJar;
using (StreamWriter streamWriter = new StreamWriter(login_httpWebRequest.GetRequestStream()))
{
streamWriter.Write("{username:xxxxxx,password:yyyyyyy}");
}
var httpResponse = (HttpWebResponse)login_httpWebRequest.GetResponse();
var login_cookies = httpResponse.Cookies;
logout_httpWebRequest.CookieContainer = new CookieContainer();
httpWebRequest.CookieContainer.Add(login_cookies);
using (StreamWriter streamWriter = new StreamWriter(logout_httpWebRequest.GetRequestStream()))
{
streamWriter.Write("{}");
}
var httpResponse = (HttpWebResponse)login_httpWebRequest.GetResponse();
But my C# program takes more time than the original JAVA program and then I checked the request using Fiddler tool. So I found for every request C# Tunnel to server. but JAVA program only once.
Bellow image
Green color shows requests (tunnel->login->logout) sent to server by JAVA program.
Red color shows C# program requests(tunnel->login->tunnel->logout) sent to server by C# program.
Anyone knows how to avoid tunneling for each request by C# Http client.
Have you tried using HttpClient instead of WebRequest? I wrote this up with no way to test it so hopefully it's close....
using (HttpClientHandler handler = new HttpClientHandler())
{
CookieContainer cookies = new CookieContainer();
handler.CookieContainer = cookies;
using (HttpClient httpClient = new HttpClient(handler))
{
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json; charset=UTF-8"));
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, m_base_url + "session/login");
requestMessage.Content = new StringContent("{username:xxxxxx,password:yyyyyyy}"); ;
HttpResponseMessage loginResponse = await httpClient.SendAsync(requestMessage);
// The HttpClient should already have the cookies from the login so
// no need to transfer
requestMessage = new HttpRequestMessage(HttpMethod.Get, m_base_url + "session/logout");
requestMessage.Content = new StringContent("{}");
HttpResponseMessage logoutResponse = await httpClient.SendAsync(requestMessage);
}
}

WebRequest Equivalent to CURL command

I am banging my head against a wall trying to convert a working curl command to a c# WebRequest.
I have read through quite a few postings and I was pretty sure I had the code right but it still will not work.
Can anyone see what I am doing wrong please?
Here is the working curl command:
curl -k -u x:reallylongstring -H "Content-Type: application/json" https://api.somewhere.com/desk/external_api/v1/customers.json
And this is the code I have written in c#:
WebRequest wrGETURL;
wrGETURL = WebRequest.Create("https://api.somewhere.com/desk/external_api/v1/customers.json");
wrGETURL.Method = "GET";
wrGETURL.ContentType = "application/json";
wrGETURL.Credentials = new NetworkCredential("x", "reallylongstring");
Stream objStream = wrGETURL.GetResponse().GetResponseStream();
StreamReader objReader = new StreamReader(objStream);
string responseFromServer = objReader.ReadToEnd();
But the api responds:
The remote server returned an error: (406) Not Acceptable.
Any help would be much appreciated!
Thanks
Based on Nikolaos's pointers I appear to have fixed this with the following code:
public static gta_allCustomersResponse gta_AllCustomers()
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://api.somewhere.com/desk/external_api/v1/customers.json");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Accept = "*/*";
httpWebRequest.Method = "GET";
httpWebRequest.Headers.Add("Authorization", "Basic reallylongstring");
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
gta_allCustomersResponse answer = JsonConvert.DeserializeObject<gta_allCustomersResponse>(streamReader.ReadToEnd());
return answer;
}
}
Here is my solution to post json data to using an API call or webservice
public static void PostJsonDataToApi(string jsonData)
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://api.somewhere.com/v2/cases");
httpWebRequest.ReadWriteTimeout = 100000; //this can cause issues which is why we are manually setting this
httpWebRequest.ContentType = "application/json";
httpWebRequest.Accept = "*/*";
httpWebRequest.Method = "POST";
httpWebRequest.Headers.Add("Authorization", "Basic ThisShouldbeBase64String"); // "Basic 4dfsdfsfs4sf5ssfsdfs=="
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
// we want to remove new line characters otherwise it will return an error
jsonData= thePostBody.Replace("\n", "");
jsonData= thePostBody.Replace("\r", "");
streamWriter.Write(jsonData);
streamWriter.Flush();
streamWriter.Close();
}
try
{
HttpWebResponse resp = (HttpWebResponse)httpWebRequest.GetResponse();
string respStr = new StreamReader(resp.GetResponseStream()).ReadToEnd();
Console.WriteLine("Response : " + respStr); // if you want see the output
}
catch(Exception ex)
{
//process exception here
}
}
This is the curl command I use to post json data:
curl http://IP:PORT/my/path/to/endpoint -H 'Content-type:application/json' -d '[{...json data...}]'
This is equivalent to the above curl command with C#:
var url = "http://IP:PORT/my/path/to/endpoint";
var jsonData = "[{...json data...}]";
using (var client = new WebClient())
{
client.Headers.Add("content-type", "application/json");
var response = client.UploadString(url, jsonData);
}
According to this question regarding 406: What is "406-Not Acceptable Response" in HTTP? perhaps you could try adding an Accept header to your request? Maybe curl adds that automatically.
Also there's a -k in your curl request telling it to ignore SSL validation, which I'm not sure if it affects the .NET code. In other words, does curl still work without the '-k'? Then, no worries. Otherwise, perhaps you need to tell .NET to also ignore SSL validation.

RestSharp - Authorization Header not coming across to WCF REST service

I am trying to call a locally hosted WCF REST service over HTTPS with basic auth.
This works and the Authorization header comes thru just fine and all is happy:
ServicePointManager.ServerCertificateValidationCallback = ValidateServerCertficate;
var request = (HttpWebRequest)WebRequest.Create("https://localhost/MyService/MyService.svc/");
request.Method = "GET";
request.ContentType = "application/json";
request.Headers.Add(
System.Net.HttpRequestHeader.Authorization,
"Basic " + this.EncodeBasicAuthenticationCredentials("UserA", "123"));
WebResponse webResponse = request.GetResponse();
using (Stream webStream = webResponse.GetResponseStream())
{
if (webStream != null)
{
using (StreamReader responseReader = new StreamReader(webStream))
{
string response = responseReader.ReadToEnd();
}
}
}
When I try to use RestSharp however, the Authorization header never comes thru on the request:
ServicePointManager.ServerCertificateValidationCallback = ValidateServerCertficate;
var credentials = this.EncodeBasicAuthenticationCredentials("UserA", "123");
var client = new RestSharp.RestClient("https://localhost/MyService/MyService.svc/");
var restRq = new RestSharp.RestRequest("/");
restRq.Method = Method.GET;
restRq.RootElement = "/";
restRq.AddHeader("Authorization", "Basic " + credentials);
var restRs = client.Execute(restRq);
What am i doing wrong with the RestSharp method?
I know that the AddHeader method works because this:
restRq.AddHeader("Rum", "And Coke");
will come thru, only "Authorization" seems stripped out/missing.
instead of adding the header 'manually' do the following:
var client = new RestSharp.RestClient("https://localhost/MyService/MyService.svc/");
client.Authenticator = new HttpBasicAuthenticator("UserA", "123");
I used milano's answer to get my REST service call to work (using GET)
Dim client2 As RestClient = New RestClient("https://api.clever.com")
Dim request2 As RestRequest = New RestRequest("me", Method.GET)
request2.AddParameter("Authorization", "Bearer " & j.access_token, ParameterType.HttpHeader)
Dim response2 As IRestResponse = client2.Execute(request2)
Response.Write("** " & response2.StatusCode & "|" & response2.Content & " **")
The key was making sure there was a space after the word 'Bearer' but this may apply to any type of custom token authorization header
You have to use ParameterType.HttpHeader parameter:
request.AddParameter("Authorization", "data", ParameterType.HttpHeader);
I was able to get the response from my rest API using this piece of code:
My API was returning server error and I used:
request.AddHeader("Authorization", $"Bearer {accessToken}");
var request = new RestRequest("/antiforgerytokensso", Method.Get);
restClient.Authenticator = new JwtAuthenticator(accessToken);
var response = await restClient.ExecuteAsync(request);
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));

Categories

Resources