I am working to integrate with a third-party that provides sample code for use with cURL. I've been able to successfully connect using cURL via the following command:
curl -k -d "grant_type=client_cert" --basic -u "myUserName:myPassword" -H "Content-Type: application/x-www-form-urlencoded" --cert c:\certs\myCert.pem https://vendorUrl/method
In reading the cURL docs, I believe this is what all the switches translate to:
- -k: insecure (proceed even if connection is not secure)
- -d: data. Also indicates this is a POST.
- --basic: basic auth
- -u username/password
- -H additional header
- --cert: pass certificate
I have tried many (!) different tips I've found online, so there are some lines of code that may be unnecessary. I have tried to indicate where I have interpreted cURL switches to C# in my code comments.
//Not sure if these are needed or not. ServicePointManager.Expect100Continue = true; ServicePointManager.CheckCertificateRevocationList = false; //allow every possible protocol for now just to eliminate the protocol as the source of the problem ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3; //this should be the equivalent of cURL's "-k" (insecure) switch. ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true; var certificatePath = ConfigurationManager.AppSettings.GetValue("myPath"); var clientKey = "myKey"; var clientSecret = "mySecret"; var url = "https://vendorUrl/method"; //create the request var request = new RestRequest(Method.POST); ////this should be the equivalent of cURL's -d (data) switch. no idea if this is done correctly. I have also tried adding this as "AddJsonBody()" var body = "grant_type=client_cert"; request.AddBody(body); //this should be the equivalent of cURL's "-H" (header) switch request.AddHeader("Content-Type", "application/x-www-form-urlencoded"); //Import certificate var certificates = new X509Certificate(); certificates.Import(certificatePath); var client = new RestClient { BaseUrl = new Uri(url), //this should be the equivalent of cURL's "--cert" switch ClientCertificates = new X509CertificateCollection { certificates }, //this should be the equivalent of cURL's "--basic" (Basic Auth) switch and the "-u" switch Authenticator = new HttpBasicAuthenticator(clientKey, clientSecret) }; var response = client.Execute(request); The error message I get is the dreaded "The request was aborted: Could not create SSL/TLS secure channel."
I also added trace logging as described here: The request was aborted: Could not create SSL/TLS secure channel.
I don't really know how to parse the output of the trace, but one of the last messages in the trace looks like a problem:
System.Net Information: 0 : [9232] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=IllegalMessage).
WebRequest. So if you can manage to get it working withWebRequest- it will work with RestSharp... I know that this is not very helpful but still.