Securing network traffic with TLS 1.2
Secure and encrypted network communications are a crucial part of mobile application development. Without some kind of security around the communication layer, it is trivial for a third party to eavesdrop and tamper with the messages between the client and the server. If protecting the data being transmitted is important, then some kind of cryptography must be involved to protect both the sender and the receiver from malicious eyes.
There are three important requirements to secure network communications:
- Authentication – The client and the server need some way to verify the identity of each other.
- Encryption – Encryption is used to prevent the data from being read by unauthorized agents.
- Integrity – It is important that the message is not tampered with while in transit. In order to protect the integrity of the message, a cryptographic algorithm must provide a way for the recipient to prove that the message it received is exactly the same as the message that was sent.
Transport Layer Security version 1.2 (TLS) is a protocol that uses certificates and private-public keys to satisfy these three requirements. It is the most common solution used by major cloud providers and web servers. Older versions of TLS should be avoided as they do not meet the requirements of modern, secure communications. In most cases, web servers will reject any traffic from mobile apps that do not use TLS 1.2.
In most cases, Xamarin apps should use either the .NET System.Net.Http.HttpClient class or the System.Net.WebRequest class for network calls. The HttpClient class uses a instance of HttpMessageHandler to process the results of a network call. Xamarin.Android and Xamarin.iOS both provide implementations of the HttpMessageHandler API that will determine what version of TLS the app will use.
TLS 1.2 in Xamarin.Android
Xamarin.Android provides support for TLS 1.2 on devices that are running Android 5.0 or higher by using the Java APIs by leveraging the native. Devices that are running older versions of Android lack the necessary libraries and support for TLS 1.2. If a Xamarin.Android mobile app must support TLS 1.2 then the minimum SDK level must be set to Android 5.0 (API level 20).
There are two settings in Xamarin.Android that will control what version of TLS an app uses. These can be found by right-clicking the project, then selecting Properties > Android Options > Advanced in Visual Studio on Windows, or Options > Build > Android Build > General in Visual Studio for Mac. The Advanced Android Options dialog will have two drop-down lists that control how TLS is used in network calls:
- HttpClient implementation – This sets the default HttpMessageHandler that will be used for HttpClient requests. Xamarin.Android apps should use the Android HTTP client because the Managed HttpMessageHandler only supports TLS 1.0:
- TLS implementation – Controls the defaults for the TLS implementation that will be used by WebRequests. Apps should use the Native TLS 1.2+ setting:
Using TLS 1.2 with System.Net.Http.HttpClient on Xamarin.Android
It is possible to mix and match HttpMessageHandler on a call-by-call basis when creating an HttpClient object:
// This will use the message handler specified in the project properties
var client = new HttpClient();
// Use AndroidClientHandler for all calls from this HttpClient
var client = new HttpClient(new Xamarin.Android.Net.AndroidClientHandler ());
TLS 1.2 in Xamarin.iOS and Xamarin.Mac
iOS (and macOS) has a more unified approach when it comes to TLS support. Beginning with Xamarin.iOS 10.8, all iOS applications use Apple’s native TLS implementation, which provides full TLS 1.2+ support for all applications.
Xamarin.Mac 4.8 (not yet released) will only support macOS 10.9 or higher. Previous versions of Xamarin.Mac supported macOS 10.7 or higher, but these older macOS versions lack sufficient TLS infrastructure to support TLS 1.2. To target macOS 10.7 or macOS 10.8, use Xamarin.Mac 4.6 or earlier.
Xamarin.iOS apps can set a project-wide default HttpMessageHandler for the app. This setting can be found by right-clicking the project and selecting Properties > iOS Build > Advanced in Visual Studio or Options > Build > iOS Build in Visual Studio for Mac.
There are three different choices for the default HttpMessageHandler in an app:
- Managed – A managed HttpMessageHandler. This provides the best compatibility with .NET HttpClient features. However it requires more managed code and will increase the application size in comparison to either of the following two choices.
- CFNetwork – This HttpMessageHandler is a wrapper around the native iOS CFNetwork
- NSUrlSession – This is a wrapper around the native iOS NSUrlSession This is the recommended option for Xamarin.iOS projects.
The last two, CFNetwork and NSUrlSession, are very similar in that they both utilize native iOS APIs, queues, and threads. This means that the app executable will be smaller and the app itself could have improved network performance. However, because these two handlers are wrappers, they may be missing some of the .NET HttpClient features and options.
Using TLS 1.2 with System.Net.Http.HttpClient on Xamarin.iOS
It is possible that a Xamarin.iOS app may need to use a HttpMessageHandler that is different from the project wide default. To do this, programmatically create an HttpClient object:
// This will use the HttpMessageHandler set in Project Options:
var client = new HttpClient();
// This will create an HttpClient that explicitly uses the CFNetworkHandler
var client = new HttpClient(new CFNetworkHandler());
// This will create an HttpClient that explicitly uses NSUrlSessionHandler
var client = new HttpClient(new NSUrlSessionHandler());
TLS 1.2 and System.Net.WebRequest
In contrast to the HttpClient class, WebRequest does not offer a way to programmatically change which TLS implementation to use. A WebRequest object determines if TLS should be used or not by inspecting the URI of the request:
// This URL is https, so the default TLS implementation for the
// project will be used.
WebRequest webRequest = WebRequest.Create("https://www.contoso.com/");
This means that WebRequests made on Xamarin.iOS will automatically use TLS 1.2. WebRequests made by a Xamarin.Android app will use the version of TLS is selected in the Advanced Android Options dialog.
The Xamarin documentation on cross-platform development has been updated with all the important details for on using Transport Layer Security for making secure network calls in your Xamarin app.
If you are looking for more details on TLS and .NET in general, Microsoft also has a TLS best practices guide with the .NET framework guide which provides a lot of useful information.
You can learn more with Xamarin University’s free self-guided course Consuming REST-based Web Services, which examines how to integrate with, and consume, RESTful web services in mobile apps.
Finally, Episode 37 of the Merge Conflict podcast describes some of the challenges that were faced with updating an existing mobile app to support TLS 1.2.