Managing App Transport Security — iOS & macOS

This guide discusses Apple's App Transport Security and how to manage it within your apps.

Overview

With each major upgrade of its operating systems, Apple introduces new features which all iOS and macOS developers must be aware of. In iOS 9 and macOS 10.11, a particularly important feature known as App Transport Security was introduced, hereafter referred to as ATS.

Essentially, ATS is Apple's new guard against insecure HTTP and weaker/older HTTPS connections. Apple suggests that you adopt ATS as soon as possible, regardless of whether you're creating a new app or updating an existing one. The intent is to protect your app's users from exploits inherent in older Internet protocols, so the best approach is always to work with it rather than just turn it off (an option that Apple will remove in the near future anyway).

For comprehensive details and usage specifications for ATS, please see Apple's documentation.

Prerequisites

ATS applies to both iOS and macOS apps which meet these criteria:

Valid Connections

The following conditions must be met for a connection to be allowed through ATS:

Configuring Connections

Important

While we provide this information for reference, Corona Labs does not encourage bypassing ATS for any connection since its intent is to protect users' privacy.

ATS can be configured to manage certain specific endpoints that do not meet the valid connections requirements outlined above. The following steps outline this process:

  1. Configuring ATS begins with the addition of the NSAppTransportSecurity key-value pair within the iphoneplist table of your app's build.settings file (guide):
settings =
{
    iphone =
    {
        plist =
        {
            NSAppTransportSecurity =
            {

            },
        },
    },
}
  1. Inside the NSAppTransportSecurity table, add a NSExceptionDomains key-value pair. This allows you to specify ATS exceptions for specific domains.
NSAppTransportSecurity =
{
    NSExceptionDomains =
    {

    },
},
  1. Inside the NSExceptionDomains table, include distinct key-value pairs to describe domain-specific network connection configuration exceptions. An exception domain's top-level key is the domain name string for which you want to specify a connection configuration. Because of Lua naming convention rules, you will typically need to specify these names within brackets/quotes, for instance ["example.com"].
NSAppTransportSecurity =
{
    NSExceptionDomains =
    {
        ["example.com"] =
        {

        },
    },
},
  1. Finally, to configure the exception domain, include key-value pairs which describe server-specific exceptions to your app's overall intended network behavior. For instance:
NSAppTransportSecurity =
{
    NSExceptionDomains =
    {
        ["example.com"] =
        {
            NSIncludesSubdomains = true,
            NSThirdPartyExceptionAllowsInsecureHTTPLoads = true,
        },
    },
},

The following table summarizes the valid options. For comprehensive details, please see Apple's documentation.

Key Value Description
NSIncludesSubdomains boolean An optional boolean value that, when set to true, applies the NSExceptionDomains exceptions to all subdomains of the domain whose name is the top-level key. Default is false.
NSExceptionAllowsInsecureHTTPLoads boolean An optional boolean value that, when set to true, allows insecure HTTP loads. Use this key to describe your app's intended network behavior for a domain whose security attributes you can control. Default is false.
NSExceptionRequiresForwardSecrecy boolean An optional boolean value for overriding the requirement that a server supports forward secrecy (FS). Use this key to describe your app's intended network behavior for a domain whose security attributes you can control. Default is true.
NSExceptionMinimumTLSVersion string An optional string value that specifies the minimum Transport Layer Security (TLS) version for connections. Use this key to describe your app's intended network behavior for a domain whose security attributes you can control. Default value is TLSv1.2.
NSThirdPartyExceptionAllowsInsecureHTTPLoads boolean A version of the NSExceptionAllowsInsecureHTTPLoads key to be used to configure connections for a domain whose security attributes you cannot control.
NSThirdPartyExceptionRequiresForwardSecrecy boolean A version of the NSExceptionRequiresForwardSecrecy key to be used to configure connections for a domain whose security attributes you cannot control.
NSThirdPartyExceptionMinimumTLSVersion string A version of the NSExceptionMinimumTLSVersion key to be used to configure connections for a domain whose security attributes you cannot control.
  1. Putting it together, an example ATS configuration block within build.settings may be structured like this:
settings =
{
    iphone =
    {
        plist =
        {
            NSAppTransportSecurity =
            {
                NSExceptionDomains =
                {
                    ["example.com"] =
                    {
                        NSIncludesSubdomains = true,
                        NSThirdPartyExceptionAllowsInsecureHTTPLoads = true,
                    },
                },
            },
        },
    },
}

Bypassing ATS

As a last resort, ATS can also be configured to allow insecure connections by default. This can be accomplished by including the NSAllowsArbitraryLoads key within the NSAppTransportSecurity table and setting its value to true:

NSAppTransportSecurity =
{
    NSAllowsArbitraryLoads = true,
},
Note

If you globally bypass ATS in this manner, exception domains can still be defined as outlined above. In this case, you can effectively increase restrictions on a specific server. For example, setting the value of a named server's NSExceptionAllowsInsecureHTTPLoads key to false re-enables HTTPS enforcement for that server.

Corona Simulator

Since the Corona Simulator on macOS must simulate all types of devices, including those that do not implement ATS, it turns it off for all connections.