I’ve underestimated how frequently I must use a web API in my C# programs. If you’ve ever needed to send a web request from a.NET application, you’ve probably encountered the following annoying exception message just as often as I have.
Despite being so direct, this error message confuses the majority of developers. How do you fix it and what is the cause?
An invalid certificate on the target server typically results in an exception. By default,.NET web requests must confirm the target of their requests, and developers can use the ServicePointManager to verify an unknown certificate.
If you need something that “works”, then you might use the following code.
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, errors) => { return true; };
What Is The ServicePointManager
The Microsoft docs succinctly describes the purpose of the ServicePointManager
class.
A ServicePoint object containing connection details for the host and scheme identified by the URI is returned by the ServicePointManager object in response to an application’s request to connect to an Internet resource with a Uniform Resource Identifier (URI).
For outgoing web requests, the class essentially functions as a connection manager. You must subscribe to the ServerCertificateValidationCallback
event, which fires on each certificate validation, in order to verify these connections.
ServicePointManager For Development
Use this crude validator implementation if you’re writing a console program or other quick piece of code.
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, errors) => { // local dev, just approve all certs if (development) return true; return errors == SslPolicyErrors.None ; };
The local development implementation ensures that the SSL policy is at the very least error-free.
ServicePointManager For Production
You can verify against a dictionary of certificate hashes if you believe the locations calling are legitimate and are aware of them. These certificates can either be read from disk or preloaded on the host computer. In the majority of situations, I prefer this second implementation of ServerCertificateValidationCallback
.
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, errors) => { // local dev, just approve all certs if (development) return true; return errors == SslPolicyErrors.None && validCerts.Contains(certificate.GetCertHashString()); };
The hash strings of the X509
certificates you trust are contained in the dictionary that makes up the validCerts
variable. These can be loaded from a database or a configuration file. The trusted certs can be loaded into a.NET console app, which can then output the hash strings.
var hash = X509Certificate .CreateFromCertFile("mycert.cer") .GetCertHashString();
By using trusted certificates, you can prevent any sensitive requests from being sent to untrusted servers. To minimize friction when beginning a development project, you can begin by accepting all certificates during local development; however, before deploying code into production, remember to harden your security.
Andriy Kravets is writer and experience .NET developer and like .NET for regular development. He likes to build cross-platform libraries/software with .NET.