At WWDC 2015, Apple announced “App Transport Security”

App Transport Security (ATS) enforces best practices in the secure connections between an app and its back end. ATS prevents accidental disclosure, provides secure default behavior, and is easy to adopt; it is also on by default in iOS 9 and OS X v10.11. You should adopt ATS as soon as possible, regardless of whether you’re creating a new app or updating an existing one.

If you’re developing a new app, you should use HTTPS exclusively. If you have an existing app, you should use HTTPS as much as you can right now, and create a plan for migrating the rest of your app as soon as possible. In addition, your communication through higher-level APIs needs to be encrypted using TLS version 1.2 with forward secrecy. If you try to make a connection that doesn’t follow this requirement, an error is thrown. If your app needs to make a request to an insecure domain, you have to specify this domain in your app’s Info.plist file.

By default, ATS is enabled when using NSURLSession, NSURLConnection, or CFURL in iOS 9 or OS X El Capitan. So, in the actual use case, if your app attempts to connect to any HTTP server, the “connection module” will change the http protocol to https protocol. If the server doesn’t support the latest SSL technology (TLSv1.2), the similar error shows:

CFNetwork SSLHandshake failed (-9801)
Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo=0x7fb080442170 {NSURLErrorFailingURLPeerTrustErrorKey=, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorCodeKey=-9802, NSUnderlyingError=0x7fb08055bc00 "The operation couldn’t be completed. (kCFErrorDomainCFNetwork error -1200.)", NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://yourserver.com, NSErrorFailingURLStringKey=https://yourserver.com, _kCFStreamErrorDomainKey=3}

ATS Configuration Structure

ATS is configured inside the info.plist file, under NSAppTransportSecurity dictionary. The following listing represents the overall structure:

NSAppTransportSecurity : Dictionary {
    NSExceptionDomains : Dictionary {
        <domain-name-string> : Dictionary {
            NSIncludesSubdomains : Boolean
            // Keys to describe your app’s intended network behavior for
            //    domains whose security attributes you control
            NSExceptionAllowsInsecureHTTPLoads : Boolean
            NSExceptionRequiresForwardSecrecy : Boolean
            NSExceptionMinimumTLSVersion : String
            // Keys to describe your app’s intended network behavior for
            //    domains whose security attributes you don't control
            NSThirdPartyExceptionAllowsInsecureHTTPLoads : Boolean
            NSThirdPartyExceptionRequiresForwardSecrecy : Boolean
            NSThirdPartyExceptionMinimumTLSVersion : String
        }
    }
    NSAllowsArbitraryLoads : Boolean
}

As shown above, the structure contains two major keys:

  • NSExceptionDomains – An optional dictionary of ATS exceptions for specific domains. Each value in the dictionary is itself a dictionary, and describes a domain-specific network connection configuration exception.
  • NSAllowsArbitraryLoads – An optional Boolean value that, when set to YES, disables App Transport Security (ATS) for any domains for which you do not reenable ATS by using an exception domain dictionary.

Here is the list of possible “keys” that NSExceptionDomains can use:

  • NSIncludesSubdomains – If applied ATS exceptions to all subdomains.
  • NSExceptionAllowsInsecureHTTPLoads & NSThirdPartyExceptionAllowsInsecureHTTPLoads – If allowed insecure HTTP loads.
  • NSExceptionRequiresForwardSecrecy & NSThirdPartyExceptionRequiresForwardSecrecy – If overriding the requirement that a server support forward secrecy (FS).
  • NSExceptionMinimumTLSVersion & NSThirdPartyExceptionMinimumTLSVersion – Specify the minimum Transport Layer Security (TLS) version for connections, like “TLSv1.0”, “TLSv1.1”, “TLSv1.2”. Default value is “TLSv1.2”.

Please see here for more details.

Example Cases

Here are some example use cases.

Allowing Insecure Connection to a Single Server

Add a specific domain under NSExceptionDomains.

NSAppTransportSecurity
    NSExceptionDomains
        "media-server.example.com"
            NSExceptionAllowsInsecureHTTPLoads = YES

Allowing Lowered Security to a Single Server

Specify the actual version in NSExceptionMinimumTLSVersion.

NSAppTransportSecurity
    NSExceptionDomains
        "less-secure.example.com"
            NSExceptionRequiresForwardSecrecy = NO
            NSExceptionMinimumTLSVersion = "TLSv1.0"

Using ATS For Your Servers and Allowing Insecure Connections Elsewhere

Set YES to NSAllowsArbitraryLoads to allow insecure connections and add all of your domains under NSExceptionDomains.

NSAppTransportSecurity
    NSExceptionDomains
        "domain-i-control.example.com"
            NSExceptionAllowsInsecureHTTPLoads = NO
            NSExceptionRequiresForwardSecrecy = YES
            NSExceptionMinimumTLSVersion = "TLSv1.2"
        "other-domain-i-control.example.com"
            NSExceptionAllowsInsecureHTTPLoads = NO
            NSExceptionRequiresForwardSecrecy = YES
            NSExceptionMinimumTLSVersion = "TLSv1.2"
    NSAllowsArbitraryLoads = YES

Disable ATS Entirely

Simply set YES to NSAllowsArbitraryLoads.

NSAppTransportSecurity
    NSAllowsArbitraryLoads = YES

Please Note, this is not recommended. Try to use it only for debugging!!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>