Update 6/23/15: Apple now has official documentation for App Transport Security.
With iOS 9 and OS X El Capitan, Apple has introduced App Transport Security. In a nutshell, App Transport Security enforces best practices for secure network connections — notably, TLS 1.2 and forward secrecy. In the future, Apple will also update these best practices to ensure they always reflect the latest security practices that will keep network data secure.
App Transport Security is enabled by default when using NSURLSession in iOS 9 or OS X El Capitan. Unfortunately for many developers this may mean that things break as soon as they build for iOS 9 or OS X 10.10. Fortunately Apple offers some configuration options to leverage App Transport Security where possible, while disabling it in places where you cannot support it.
You can opt-out of ATS for certain URLs in your Info.plist by using
NSExceptionDomains. Within the
NSExceptionDomains dictionary you can explicitly define URLs that you need exceptions for with ATS. The exceptions you can use are:
Each of these keys allows you to granularly disable ATS or particular ATS options on domains where you are unable to support them.
In the first beta of iOS 9, these keys are incorrect and instead you’ll need to use the following:
These keys will undoubtedly be fixed in a future seed. If you can, you should use the first set of keys above that Apple is officially supporting, though if you’re using the temporary keys, they should continue to work in future betas. Thanks to Juan Leon for bringing this to my attention—I was told the same in the labs.
Below are examples of different scenarios developers may encounter.
Example A: ATS for all
This is the easiest one. The only thing you need to do is use NSURLSession. If you’re targeting iOS 9 or OS X El Capitan or later, ATS’s best practices will apply to all of your NSURLSession traffic.
Example B: ATS for all, with some exceptions
If you expect all of your domains to work with ATS, except a few that you know will not work, you can specify exceptions for where ATS should not be use, while leaving all other traffic opted in. For this scenario, you’ll want to use an
NSExceptionDomains to specify the domains for which you wish to override ATS’s default settings. To opt-out an entire domain or sub-domain, create a dictionary for the URL you want to opt-out of ATS, then set
NSExceptionAllowInsecureHTTPLoadsto true. You can also specify more specific rules you wish to override with
NSExceptionMinimumTLSVersion if you don’t want to completely disable ATS on those domains.
Example C: ATS disabled, with some exceptions
Conversely, you may only want ATS to work on domains you specifically know can support it. For example, if you developer a Twitter client, there will be countless URLs you may want to load that may not be able to support ATS, though you would want things like login calls, and other requests to Twitter to use ATS. In this case you can disable ATS as your default, then specify URL which you do wish to use ATS.
In this case you should set
NSAllowArbitraryLoads to true, then define the URLs that you want to be secure in your
NSExceptionDomains dictionary. Each domain you wish to be secure should have its own dictionary, and the
NSExceptionAllowInsecureHTTPLoads for that dictionary should be set to false.
Example D: Downgraded ATS
In some cases you may want ATS on all, or some, or your URLs, but are not ready to fully support all of ATS’s best practices. Perhaps your servers support TLS1.2, but don’t yet support forward secrecy. Rather than completely disabling ATS on the affected domains, you can leave ATS enabled, but disable forward secrecy. In this scenario you would create an
NSExceptionDomains dictionary, a dictionary entry for each domain you need to override settings for, then set the
NSExceptionRequiresForwardSecrecy value to false. Similarly, if you wish to have forward secrecy enabled, but need the minimum TLS version to be lower, you can define your supported TLS version with the
Example E: NSA-friendly Mode
If you want to opt-out of ATS entirely (which you really shouldn’t do unless you fully understand the implications), you can simply set
NSAllowArbitraryLoads to true in your Info.plist.
You may have noticed a few keys that appear to be duplicates of others keys with the addition of “ThirdParty” in the name.
Functionally these keys will have the same result as the keys that don’t have “ThirdParty” in them. The actual code being invoked behind the scenes will be identical regardless of whether you use the ThirdParty keys or not. You should probably use whichever key best fits your exceptions, but no need to overthink it.
While most security features for ATS are enabled by default, certificate transparency is one you must opt-in to. If you have certificates which support certificate transparency, you can enable certificate transparency checks with the
NSRequiresCertificateTransparency key. Again, if your certificates don’t yet support certificate transparency, by default this check will be disabled.
If you need help debugging issues that arise from having App Transport Security enabled, setting
1 will log all NSURLSession errors including the URL that was called and the ATS error that resulted. Be sure to file radars for any issues you encounter so that ATS can be improved and flexibility expanded.
All of the above information was provided in Apple’s Networking with NSURLSession session at WWDC 2015. Finally, Apple emphasized in the talk to report any issues that you run into and keep any eye out for any changes that may be coming in future betas.