Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

System.Net.WebException thrown when consuming a web service over HTTPS

When making a call to a web service running on a server using HTTPS my application throws a System.Net.WebException with the message "The underlying connection was closed: Could not establish trust relationship with remote server". I'm not sure how to get around this issue and successfully make the call.

like image 943
Brad Avatar asked Jul 01 '11 19:07

Brad


2 Answers

After some research, I found a blog entry by Jan Tielens which explains what is going on and a workaround for my problem:

When you browse to a HTTPS site, you probably get a dialog window asking you if you want to trust the certificate provided by the webserver. So the responsibility of accepting the certificate is handled by the user. Let's get back to the webservice scenario, if you want to invoke a webservice located on a webserver which uses SSL and HTTPS there is a problem. When you make the call from code, there is no dialog window popping up, and asking if you trust the certificate (luckily because this would be pretty ugly in server-side scenarios); probably you'll get following exception:

An unhandled exception of type System.Net.WebException occurred in System.dll
Additional information: The underlying connection was closed: Could not establish trust relationship with remote server.

But there is a solution for this problem, you can solve this in your code by creating your own CertificatePolicy class (which implements the ICertificatePolicy interface). In this class you will have to write your own CheckValidationResult function that has to return true or false, like you would press yes or no in the dialog window. For development purposes I've created the following class which accepts all certificates, so you won't get the nasty WebException anymore:

public class TrustAllCertificatePolicy : System.Net.ICertificatePolicy
{
    public TrustAllCertificatePolicy() { }

    public bool CheckValidationResult(ServicePoint sp, X509Certificate cert, WebRequest req, int problem)
    {
        return true;
    }
}

As you can see the CheckValidationResult function always returns true, so all certificates will be trusted. If you want to make this class a little bit more secure, you can add additional checks using the X509Certificate parameter for example. To use this CertificatePolicy, you'll have to tell the ServicePointManager to use it:

System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();

This must be done (one time during the application life cycle) before making the call to your webservice.

like image 133
Brad Avatar answered Nov 07 '22 07:11

Brad


If you're using a self signed SSL cert, or an untrusted SSL cert, you can tell your application to ignore it (If you really want to ignore it). e.g.

ServicePointManager.ServerCertificateValidationCallback = _
      new RemoteCertificateValidationCallback(IgnoreSelfSSL)

public bool IgnoreSelfSSL(ServicePoint sp, X509Certificate cert,WebRequest req, int problem) { 
   return true; 
}

You can place the callback anywhere that will be hit prior to executing your service call.

like image 3
George Johnston Avatar answered Nov 07 '22 06:11

George Johnston