HTTP Communication with C# – (Part III)

Handling secure connections

The previous two articles of this mini-series showed how to perform a GET and a POST request on normal HTTP URLs. The last step to have a complete HTTP communication client is to handle HTTPS connections which require certificate verification. This article describes how SSL communication can be handled.

The first steps performed in both the GET and the POST request articles was to set up the connection object. For a secure connection, we need to use SSL (Secure Socket Layer). The handling of SSL is defined while defining the connection by setting the ServicePointManager.ServerCertificateValidationCallback property. This property shall point to the method that is used for certificate verification.

  1. HttpWebRequest httpRequest = null;
  2.  
  3. try
  4. {
  5.   httpRequest = WebRequest.Create(<URL>) as HttpWebRequest;
  6.   httpRequest.Method = WebRequestMethods.Http.Get;
  7.  
  8.   ServicePointManager.ServerCertificateValidationCallback += MyCertificateValidator;
  9. }
  10. catch (NotSupportedException nse)
  11. { 
  12.   // Handle Error
  13. }
  14. catch (ArgumentNullException ane)
  15. {
  16.   // Handle Error
  17. }
  18. catch (SecurityException se)
  19. {
  20.   // Handle Error
  21. }
  22. catch (UriFormatException ufe)
  23. {
  24.   // Handle Error
  25. }

Verifying the certificate

Verification of the remote server certificate is done inside a method implementing the RemoteCertificateValidationCallback delegate. The method is then assigned to the property ServicePointManager.ServerCertificateValidationCallback which is called when a certificate is received. In this article the method implementing the delegate is called MyCertificateValidator. The method is defined as

  1. private static bool MyCertificateValidator (
  2.     object sender,
  3.     X509Certificate certificate, //The certificate received from the remote server
  4.     X509Chain chain, //The chain of authorities linked with by the certificate
  5.     SslPolicyErrors sslPolicyErrors) //Determines if the certificate contains errors
  6. {
  7.     // Handle certificate
  8. }

The method returns a boolean value indicates whether the certificate is accepted. When a certificate is accepted the communication with the remote server takes place otherwise the connection is closed. Therefore if all certificates, valid or not, are to be accepted all that is required is to always return true.

  1. //Accept all SSL certificates
  2. private static bool MyCertificateValidator (
  3.     object sender,
  4.     X509Certificate certificate,
  5.     X509Chain chain,
  6.     SslPolicyErrors sslPolicyErrors)
  7. {
  8.     return true;
  9. }

On the other hand if a more selective mechanism is required, the method parameters can be used to obtain detailed information about the certificate. For example, let’s consider that only certificates with no error are accepted, the rest are rejected. The method can be slightly changed to return the result of our selective decision as:

  1. //Accept all SSL certificates
  2. private static bool MyCertificateValidator (
  3.     object sender,
  4.     X509Certificate certificate,
  5.     X509Chain chain,
  6.     SslPolicyErrors sslPolicyErrors)
  7. {
  8.     return sslPolicyErrors == SslPolicyErrors.NONE;
  9. }

More elaborate solutions can be done by analysing the parameters. Some example of elaborate selections are to accept only a specific certificate or from a specific certification authority.

Conclusion

This article concludes this three-part series about HttpWebRequest class. The series shows how to perform a GET, a POST, and how to handle HTTPS connections.

With this article we are also launching a library that will be amended and enhanced with future blog posts. The library can be downloaded from here.

Articles

References