Securing communications between applications and services is extremely important, and mobile apps are no exception. Even if you use an encrypted channel based on HTTPS, you should never completely trust the identity of the target. For example, an attacker could easily discover the URL your application is pointing to, and put a fake certificate in the middle of the communication between an application and the server, thus intercepting the communication. This is extremely dangerous especially if the application handles sensitive data. In order to avoid this, a technique called certificate pinning can be used to dramatically reduce the risk of this kind of man-in-the-middle attack. This article describes how to implement certificate pinning in Xamarin.Forms, making your mobile apps more secure.
When Do You Need Certificate Pinning?
Generally speaking, you should implement certificate pinning every time you build apps that handle sensitive data and that call HTTPS URLs. Additionally, many enterprises make strict security checks before validating and distributing an app, even if for internal use only, including penetration tests. Penetration tests search for security holes in an application, and simulating a man-in-the-middle attack with a fake certificate is a common test scenario. By implementing certificate pinning, you avoid the risk of certificate replacement and this penetration test will pass.
What Do You Need To Implement Certificate Pinning?
In order to implement certificate pinning, you will need the valid certificate’s public key. This can be provided by your system administrator. For demonstration or development purposes, you can also create a self-signed certificate and retrieve the public key on your own. I won’t cover this scenario here, since the documentation from Microsoft has an excellent coverage here.
How It Works
In Xamarin.Forms, you typically use the System.Net.Http.HttpClient class to send requests over the network, using methods such as GetAsync, PostAsync, PutAsync, and DeleteAsync. Under the hoods, HttpClient relies on the System.Net.HttpWebRequest class. The behavior of the latter can be influenced working with the System.Net.ServicePointManager class, which can be instructed to check what kind of security protocol is being used and to validate the certificate at every Web request. For a better understanding, create a new Xamarin.Forms project in Visual Studio 2017. The attached sample solution is based on .NET Standard as the code sharing strategy. When ready, add the following class,
- public class EndpointConfiguration
- {
- // Replace with the public key of your company's certificate
- public const string PUBKEY = "Y O U R V A L I D K E Y G O E S H E R E";
- // Replace with a fake key you want to use for testing
- public const string PUBKEYFAKE = "Y O U R F A K E K E Y G O E S H E R E";
- }
In this class, you can store both the valid and fake public keys. In the real world, you might want to encrypt the real public key or you might consider other options to store it. The next step is setting up the ServicePointManager class. In App.xaml.cs, add the following method (which requires a using System.Net directive):
- public static void SetupCertificatePinningCheck()
- {
- ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
- ServicePointManager.ServerCertificateValidationCallback = ValidateServerCertificate;
- }
This code assigns the ServicePointManager.SecurityProtocol with the type of protocol you want to check, while ServerCertificateValidationCallback represents the action that must be executed to check if the certificate is valid. The following code demonstrates this:

vishnuprabhu ramachandranPosted Apr 1, 2019, 6:31 AM
Use httpclient with handler like this, this will trigger everytime . var handler = new HttpClientHandler { UseProxy = true, AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate }; var client = new HttpClient(handler) { BaseAddress = new Uri(baseUrl) };
SairamPosted Dec 26, 2018, 11:51 PM
// The following call will cause ValidateServerCertificate to be executed // before accessing the resource var response = await client.GetAsync("/mydata"); This is not causing any validation (ValidateServerCertificate) , Could you please let me know the reason behind this for not being called / invoked. I have used your implementation on our Xamarin forms (.Net standard - 2.0) project, but still its not being fired. :( Could you please help me on this ?
Steve HurcombePosted Sep 7, 2018, 11:37 AM
Hi, Can I just check something? My understanding of MitM attacks is that my requests are intercepted with the effect that instead of a certificate for https://www.google.com protecting my connection I would see https://www.badguy.com. *I* would expect an exception to be thrown to indicate that the certificate common names do not match, much like browsers do. Are you saying that doesn't happen, or are you saying that isn't strict enough?
Gajendra JangidPosted Mar 10, 2018, 6:13 AM
Great article........................