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

let result = 
        let request = 
            |> WebRequest.Create

        let response = 
            request.GetResponse ()

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

        Ok parsed
    | ex ->      
        Error ex

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

SSL certificate validation exception
"The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel."
"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 = 
    |> 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!