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;
Related
I have a WPF application and that calling 4 web services (Written with Java) on the same base URL and it was working perfectly until I install google chrome. I installed chrome and I've got this error:
Could not establish secure channel for SSL/TLS C# Web service
I didn't write another code. That happened for just I installed chrome then I remove chrome but didn't work and I tried system restore, uninstall eset smart security and I cleaned all windows(8.1 single languages) certificate. So how can I figure it out? Here is my web service caller
public string call(string url, string json)
{
try
{
var webrequest = (HttpWebRequest)WebRequest.Create(url);
var key = JsonConvert.SerializeObject(LoginService.SessionData.SessionKey);
UTF8Encoding uTF8Encoding = new UTF8Encoding();
byte[] requestBytes = uTF8Encoding.GetBytes(json);
WebClient client = new WebClient();
webrequest.Method = "POST";
webrequest.Headers.Add("SESSION_KEY", LoginService.SessionData.SessionKey);
webrequest.ContentType = "application/json";
webrequest.ContentLength = requestBytes.LongLength;
Stream requestStream = webrequest.GetRequestStream();//here the exception
requestStream.Write(requestBytes, 0, requestBytes.Length);
using (var response = webrequest.GetResponse())
using (var reader = new StreamReader(response.GetResponseStream()))
{
var responseBuf = reader.ReadToEnd();
String responseJson = Convert.ToString(responseBuf);
return responseJson;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return null;
}
By my observation there are a large number of services over the last several months that are turning off SSL and/or older TLS versions to mitigate security problems inherent in them.
Anywhere within the AppDomain you can just force the connection to use TLS 1.2 like this:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
You can also OR together multiple versions if you need to support older ones as well:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12
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.
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?
It is the first time I have to use certificate authentication.
A commercial partner expose two services, a XML Web Service and a HTTP service. I have to access both of them with .NET clients.
What I have tried
0. Setting up the environment
I have installed the SSLCACertificates (on root and two intermediate) and the client certificate in my local machine (win 7 professional) using certmgr.exe.
1. For the web service
I have the client certificate (der).
The service will be consumed via a .NET proxy.
Here's the code:
OrderWSService proxy = new OrderWSService();
string CertFile = "ClientCert_DER.cer";
proxy.ClientCertificates.Add(new System.Security.Cryptography.X509Certificates.X509Certificate(CertFile));
orderTrackingTO ot = new orderTrackingTO() { order_id = "80", tracking_id = "82", status = stateOrderType.IN_PREPARATION };
resultResponseTO res = proxy.insertOrderTracking(ot);
Exception reported at last statement: The request failed with an empty response.
2. For the HTTP interface
it is a HTTPS interface I have to call through POST method.
The HTTPS request will be send from a .NET client using HTTPWebRequest.
Here's the code:
string PostData = "MyPostData";
//setting the request
HttpWebRequest req;
req = (HttpWebRequest)HttpWebRequest.Create(url);
req.UserAgent = "MyUserAgent";
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
req.ClientCertificates.Add(new System.Security.Cryptography.X509Certificates.X509Certificate(CertFile, "MyPassword"));
//setting the request content
byte[] byteArray = Encoding.UTF8.GetBytes(PostData);
Stream dataStream = req.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
//obtaining the response
WebResponse res = req.GetResponse();
r = new StreamReader(res.GetResponseStream());
Exception reported at last statement: The request was aborted: Could not create SSL/TLS secure channel.
3. Last try: using the browser
In Chrome, after installing the certificates, if I try to access both urls I get a 107 error:
Error 107 (net::ERR_SSL_PROTOCOL_ERROR)
I am stuck.
The following should help you identify the issue, here are two methods to test SSL connectivity one tests the site whilst the other is a callback method to identify why SSL failed. If nothing else it should give you a better idea why it is failing.
When the method is called it will pop up with the select certificate dialog box, obviously when you do this for real you'll want to read from the cert store automatically. The reason I have put this in is because if no valid certificate is found then you will know your problem is with the way the certificate is installed.
The best thing to do is put this code in a simple console app:
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using System.Net;
private static void CheckSite(string url, string method)
{
X509Certificate2 cert = null;
ServicePointManager.ServerCertificateValidationCallback += ValidateRemoteCertificate;
X509Store store = new X509Store(StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection certcollection = (X509Certificate2Collection)store.Certificates;
// pick a certificate from the store
cert = X509Certificate2UI.SelectFromCollection(certcollection,
"Caption",
"Message", X509SelectionFlag.SingleSelection)[0];
store.Close();
HttpWebRequest ws = (HttpWebRequest)WebRequest.Create(url);
ws.Credentials = CredentialCache.DefaultCredentials;
ws.Method = method;
if (cert != null)
ws.ClientCertificates.Add(cert);
using (HttpWebResponse webResponse = (HttpWebResponse)ws.GetResponse())
{
using (Stream responseStream = webResponse.GetResponseStream())
{
using (StreamReader responseStreamReader = new StreamReader(responseStream, true))
{
string response = responseStreamReader.ReadToEnd();
Console.WriteLine(response);
responseStreamReader.Close();
}
responseStream.Close();
}
webResponse.Close();
}
}
/// <summary>
/// Certificate validation callback.
/// </summary>
private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors error)
{
// If the certificate is a valid, signed certificate, return true.
if (error == System.Net.Security.SslPolicyErrors.None)
{
return true;
}
Console.WriteLine("X509Certificate [{0}] Policy Error: '{1}'",
cert.Subject,
error.ToString());
return false;
}