F#: Disabling SSL Certificate validation

Yesterday I wanted to download some content off a website with F#, however unfortunately the certificate of the website was expired.

    let result = 
        try
            let request = 
                "https://somewebsite/with/expired/ssl/certificate/data.json?paramx=1&paramy=2"
                |> WebRequest.Create

            let response = 
                request.GetResponse ()

            // parse data
            let parsed = "..." 

            Ok parsed
        with
        | ex ->      
            Error ex

If we execute this, then result would be of Error with the following exception:

SSL certificate validation exception
SSL certificate validation exception
ex.Message
"The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel."
ex.InnerException.Message
"The remote certificate is invalid according to the validation procedure."

So how do we fix this?

The solution is to set the following code at startup of the application (or at least before the first call):

ServicePointManager.ServerCertificateValidationCallback <- 
    new RemoteCertificateValidationCallback(fun _ _ _ _ -> true)

Notice that you should not do this, because this does not validate the certificate at ALL!
Also, this is for ALL calls, if you want to do it on a specific call you need to do make some changes.

First of all, it doesn’t work with WebRequest.Create, you need to use WebRequest.CreateHttp, or cast the WebRequest to HttpWebRequest, as the property we need, ServerCertificateValidationCallback is not available on WebRequest, only on HttpWebRequest. The resulting code looks like this:

            let request = 
                "https://somewebsite/with/expired/ssl/certificate/data.json?paramx=1&paramy=2"
                |> WebRequest.CreateHttp

            request.ServerCertificateValidationCallback <- new RemoteCertificateValidationCallback(fun _ _ _ _ -> true)

            let response = 
                request.GetResponse ()

Again, don’t do this in production!

If need be, do it on a single HttpWebRequest, like the last example, and write some code so that you ignore the expiration part, but leave in place the validation part.

Code on Github!