Calling Web Services That Use Self-Signed Certificates
When you try to call a web service that uses a self-signed certificate from a client application you get the following error:
The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
This make sense since if you access the site directly in your browser you get an invalid certificate message. When you look at the details of the error it states that the certificate cannot be verified up to a trusted certification authority. This is not a big issue when using the browser since you can accept the certificate, and even add install the certificate so you don’t get the error on subsequent calls to the web services.
There are 2 ways you can fix this issue.
1) You can install the certificate on all desktops/servers the client application is running on. For a desktop application used by tons of people this is really not a good solution, and even for web application this still could become a maintenance/support nightmare.
2) The other way is to add some code to your project that allows your application to ignore the certificate error. Below are the instructions on how to do this in VS 2003 and VS2005/2008.
VS2003
1) Create a class files that contains the following code (I recommend calling the file Certificates.cs).
1 using System.Net;
2 using System.Security.Cryptography.X509Certificates;
3
4 /// <summary>
5 /// Class to handle any certificate specific code
6 /// </summary>
7 public class Certificates
8 {
9 }
10
11
12 /// <summary>
13 /// Class to overide policy so calling a web service with a
14 /// self-signed cert works.
15 /// </summary>
16 public class SelfSignedPolicy : ICertificatePolicy
17 {
18 public bool CheckValidationResult(ServicePoint srvPoint,
19 X509Certificate cert,
20 WebRequest request,
21 int certificateProblem)
22 {
23 if (certificateProblem == 0 ||
24 certificateProblem == -2146762487)
25 return true;
26
27 return false;
28 }
29 }
2) Add the following line to the Application_BeginRequest event or the OnInit event of any page that needs to call a web services that uses a self-signed cert.
1 System.Net.ServicePointManager.CertificatePolicy = New SelfSignedPolicy
VS2005/2008
1) Create a class files that contains the following code (I recommend calling the file Certificates.cs).
1 using System.Net.Security;
2 using System.Security.Cryptography.X509Certificates;
3
4 class Certificates
5 {
6 public static bool ValidateRemoteCertificate(object sender,
7 X509Certificate certificate,
8 X509Chain chain,
9 SslPolicyErrors policyErrors)
10 {
11 //Return True to force the certificate to be accepted.
12 //Needed so that calling web services with self-signed certs will work.
13 return true;
14 }
15 }
2) Add the following lines to the Application_BeginRequest event in the global.asx file or the OnInit event of any page that needs to call a web services that uses a self-signed cert.
1 using System;
2 using System.Net;
3 using System.Net.Security;
4
5
6 protected void Application_BeginRequest(Object sender, EventArgs e)
7 {
8 ServicePointManager.ServerCertificateValidationCallback =
9 new RemoteCertificateValidationCallback
10 (Certificates.ValidateRemoteCertificate);
11 }
Summary
Of course, ignoring the certificate errors within the code could open up a security risk depending on what it is being used for. Therefore, you need to look at each situation this could be used and decide if this is the right approach to take based on the risks. As a developer it is up to you to look at the risks, what problem is being solved and the priority of the issue to determine whether to implement a particular solution.
Also, in most situations I would wrap the code in the Application_BeginRequest or OnInit functions so that they only run when in a Dev/QA environment. There should not be any reason you would need a production site to access web services running under a self-signed cert (or an invalid certificate). Since this can be done in many different ways, the code to do that is not shown in the examples above.
[AddThis]