I'm trying to access some data from a service into my windows service.
This is the code in one of the threads:
HttpWebRequest webrequest = HttpWebRequest.Create(url + "/data.json?auth_token=" + authenticationToken);
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
System.Net.ServicePointManager.ServerCertificateValidationCallback =
((sender, certificate, chain, sslPolicyErrors) => true);
webrequest.Method = "GET";
webrequest.ContentType = "application/jsonp";
HttpWebResponse webresponse = (HttpWebResponse) webrequest.GetResponse();
Encoding enc = System.Text.Encoding.GetEncoding("utf-8");
StreamReader loResponseStream = new StreamReader(webresponse.GetResponseStream(), enc);
result = loResponseStream.ReadToEnd();
It was working properly before. But since few days, it is giving error:
The remote server returned an error: (403) Forbidden. at System.Net.HttpWebRequest.GetResponse()
EDIT:
If I try the request through browser, I get the response properly, but not through windowa service!
It was working properly before. But since few days, it is giving error
First thing to check: has the certificate expired?
Related
I have a token request that works on Postman on a server.
No body, just basic authentication with username and password:
However, I have this code below that returns the error:
The request was aborted: Could not create SSL/TLS secure channel.
Here is the code below:
string responsedata = string.Empty;
String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password));
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlToken);
request.Method = "POST";
request.Headers.Add("Authorization", "Basic " + encoded);
request.PreAuthenticate = true;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using (Stream stream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(stream))
{
responsedata = reader.ReadToEnd();
}
What am I doing worng?
I suspect your problem is related to the SecurityProtocol your application runs on.
Try running this before your request.
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
The endpoint your trying to connect probably requires a higher version of Tls than what your application is providing.
The default value of this is defined by the system it runs on see:
https://learn.microsoft.com/en-us/dotnet/api/system.net.securityprotocoltype?view=net-7.0#system-net-securityprotocoltype-systemdefault
So when running on an older OS this often is too low for modern API endpoints.
You can test this by enabling or disabling specific versions of TLS/SSL in Postman, look for "Protocols disabled during handshake" in the settings tab for your request.
Like Neil Moss already commented above...
Think you are in use of untrusted certificate on server side so try to ignore certificate validation...
request.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
i am doing one project which will connect to some broker.. it will send a request and get response from server. I need to handle 2 request. one is authentication request and second is approve request. My authentication request is working fine but my approve request is failing with "unauthorized" error. Can someone please guide me whats going wrong. There API says we need to send all data in header with GET as method.Thats the reason I have added as custom headers. Help will be highly appreciated.
HttpWebRequest webrequest = (HttpWebRequest)HttpWebRequest.Create(www.someurl.com);
webrequest.Headers.Add("Machine", Dns.GetHostName());
webrequest.Headers.Add("Authorization", "bearer" + LoginToken); //This token I get during authentication. i also tried removing the word "bearer" still it is failure.
webrequest.Headers.Add("username", requestList[0].userid);
webrequest.Headers.Add("messageType", "SS");
webrequest.Headers.Add("customerUniqueTransactionId", requestList[0].locateId);
webrequest.Headers.Add("scageUserId", requestList[0].userid);
webrequest.Headers.Add("accountNumber", requestList[0].account);
webrequest.Headers.Add("security", requestList[0].symbol);
webrequest.Headers.Add("currencyId", "024");
webrequest.Headers.Add("orderQuantity", requestList[0].shares.ToString());
webrequest.Headers.Add("tifInd", "IOC");
webrequest.Headers.Add("repCodeId", "1980");
webrequest.Headers.Add("overrideException", "N");
webrequest.Accept = "application/json";
webrequest.ContentType = "application/json";
**webrequest.Method = "GET";**
HttpWebResponse resp = (HttpWebResponse)webrequest.GetResponse();
Stream oRespStrm = resp.GetResponseStream();
using (StreamReader oStrmRead = new StreamReader(oRespStrm))
{
responseFromServer = oStrmRead.ReadToEnd();
}
Our .NET code is posting using JSON to an HTTPS REST API. It works on machines from Vista up (I think they all have .NET 4.5), however, we need to support down to Win XP with .Net 4.0 and on that machine our code fails on the last line shown below.
If we change the URI to HTTP from HTTPS, it works fine. A number of the lines you see below (such those for CertificateValidationCallBack) were added in an attempt to fix this issue).
BIG FLAG: We have noticed that on this XP machine, IE 8 gives "Internet Explorer cannot display the webpage" over HTTPS, though HTTP is fine. We added the CertificateValidationCallBack handler hoping it would get around this issue. I'm not sure it does.
Some information about the server configuration. It is an EC2 instance behind an ELB. The ELB holds the SSL cert and sends data received from port 443 to port 80. Apache on the EC2 instance just deals with port 80.
ADDED: sslchecker.com shows a good certificate.
private static bool CertificateValidationCallBack(
object sender,
System.Security.Cryptography.X509Certificates.X509Certificate certificate,
System.Security.Cryptography.X509Certificates.X509Chain chain,
System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
return true;
}
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
webRequest.PreAuthenticate = true;
using (var client = new WebClient())
{
client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
try
{
string responseString ;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
ServicePointManager.ServerCertificateValidationCallback = CertificateValidationCallBack;
_webEx = null;
webRequest.ContentType = "application/json";
webRequest.Method = "POST";
byte[] bytes = System.Text.Encoding.ASCII.GetBytes(credsString);
// webRequest.ContentLength = bytes.Length;
webRequest.KeepAlive = false;
webRequest.Timeout = -1;
System.IO.Stream os = webRequest.GetRequestStream();
os.Write(bytes, 0, bytes.Length); //Push it out there
os.Close();
System.Net.WebResponse resp = webRequest.GetResponse();
. . . . .
}
}
I need to hit a service to obtain the app ticket to authenticate against another service. The solution is hosted on a endpoint.
I tried using the POSTMAN app in google chrome and it succeeds and returns me the AppID. When I submit the (POST)request in POSTMAN app, it prompts for a certificate. When I select the correct certificate the call succeeds.
I need to implement the same in C# (in a web application)
I tried using the RestSharp.RestClient library and am constantly getting the following error:
"Client certificate not found in site certificates".
Attaching the code for reference.
var client = new RestSharp.RestClient("MyUrl");
var request = new RestSharp.RestRequest("pksecure/oauth20_clientcredentials.srf", RestSharp.Method.POST);
request.AddParameter("grant_type", "client_credentials");
request.AddParameter("param2", "value2");
request.AddParameter("scope", "machinename");
client.ClientCertificates = new System.Security.Cryptography.X509Certificates.X509CertificateCollection();
client.ClientCertificates.Add(new System.Security.Cryptography.X509Certificates.X509Certificate(
#"E:\MyCertificate.pfx"
, "MyPassword"
));
System.Net.ServicePointManager.ServerCertificateValidationCallback +=
delegate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate cert, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslError)
{
bool validationResult = true;
return validationResult;
};
var response = client.Execute(request);
var content = response.Content; // raw content as string
Pls. help to make this call using the mutual TLS.
TIA,
Sam.
I am not sure why I was not able to get it done using RestSharp.
But I could get it working by using HttpWebRequest Instead.
Also, earlier I was using the Certficate.Pfx file which caused the error. Using the Certificate.Cer file solved the issue.
Posting the code for reference:
var request = (HttpWebRequest)WebRequest.Create("MyURL/oauth20_clientcredentials.srf");
var postData = "grant_type=client_credentials";
postData += "¶m2=value2";
postData += "&scope=" + HttpUtility.UrlEncode("machinename");
var data = Encoding.ASCII.GetBytes(postData);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
request.ClientCertificates.Add(new System.Security.Cryptography.X509Certificates.X509Certificate(#"E:\MyCertificate.cer"));
var response = (HttpWebResponse)request.GetResponse();
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
return appToken;
Thanks,
Sam Jayander Thiagarajan.
Here is the scenario. I have written code use a digital certificate to GET cookies from a secured url, to in turn POST data back to another url using the retrieved cookies and same digital certificate. The GET works and cookies are retrieved, the POST comes back with an error 500. I installed fiddler to see what was going on...POST looks fine...cookies are present. I used the feature in fiddler that allows creating a request via drag and drop. POST the exact same POST recorded from C# code that was recorded in fiddler and it works!
What is Fiddler doing that Visual Studio is not? It must be doing something if fiddler can POST the data but Visual Studio returns an error 500. Here is the code below:
X509Certificate cert = new X509Certificate("mycert.pfx", "certpassword");
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://servertoGETcookies/fileUpload.html");
req.CookieContainer = new CookieContainer();
req.Method = "GET";
req.ClientCertificates.Add(cert);
HttpWebResponse Response = (HttpWebResponse)req.GetResponse();
CookieCollection ck = req.CookieContainer.GetCookies(req.RequestUri);
string strcookie = ck[0].Value;
string strcookie2 = ck[1].Value;
Response.Close();
req = (HttpWebRequest)WebRequest.Create("https://servertoPOSTdatawithcookies/main");
req.CookieContainer = new CookieContainer();
Cookie auth = new Cookie("_wl_authcookie_", strcookie2);
Cookie jsess = new Cookie("JSESSIONID", strcookie);
auth.Domain = "server";
jsess.Domain = "server";
req.CookieContainer.Add(auth);
req.CookieContainer.Add(jsess);
req.ClientCertificates.Add(cert);
req.Method = "POST";
Byte[] data = ReadByteArrayFromFile("filewithdatatoPOST.txt");
req.ContentLength = data.Length;
Stream myStream = req.GetRequestStream();
myStream.Write(data, 0, data.Length);
myStream.Close();
HttpWebResponse Response2 = (HttpWebResponse)req.GetResponse();
Stream strm = Response2.GetResponseStream();
StreamReader sr2 = new StreamReader(strm);
Response2.Close();
Does your code work if you set
req.ServicePoint.Expect100Continue = false;
on all your WebRequests?
Solved!!! It wasn't related to the Expect100Continue.
So after weeks of troubleshooting....6 different programmers....I figured it out. I'm not sure if this is always true, but in this scenario the problem was that the url we were getting cookies from:
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://servertoGETcookies/fileUpload.html");
was not the same as the url that we were posting the data back to:
req = (HttpWebRequest)WebRequest.Create("https://servertoPOSTdatawithcookies/main");
Getting the cookies and posting back to the same url fixed the issue:
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://servertoGETandPOSTcookies/main");
req = (HttpWebRequest)WebRequest.Create("https://servertoGETandPOSTcookies/main");