iOS9 App Transport Security

iOS9 App Transport Security

Warning: this post is indented for temporarily resolve problem about apps, which do not use HTTPS internally for working with iOS9. Please update your app with HTTPS and remove the workaround, if you have ever applied.

What the hell is App Transport Security?

At WWDC 2015, Apple announced “App Transport Security” for iOS 9 and OSX 10.11 El Capitan. Look at What’s New in iOS and you can see the following:

App Transport Security (ATS) lets an app add a declaration to its Info.plist filethat specifies the domains with which it needs secure communication. ATS prevents accidental disclosure, provides secure default behavior, and is easy to adopt. 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 simple terms, this means that if your application attempts to connect to any HTTP server (in this example, yourserver.com) that doesn’t support the latest SSL technology (TLSv1.2), your connections will fail with an error like this:

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=<SecTrustRef: 0x7fb08043b380>, 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}

Curiously, you’ll notice that the connection attempts to change the http protocol to https to protect against mistakes in your code where you may have accidentally misconfigured the URL. In some cases, this might actually work, but it’s also confusing.

DO NOT disable ATS!

Protecting personal data from being compromised over insecure wireless connections, among other things, is great for users. The reason why Apple is pushing so aggressively to force secure connections is because it is so good for users. If your application is connecting to third party APIs that you can’t control (note that our case study – Beauty Me – is currently connecting to web server without HTTPS, at least for now), then you should temporarily update your plist to allow your app work correctly.

How to Bypass App Transport Security

Unfortunately, the pre-release documentation doesn’t currently include any references to this key, so many developers who are testing their preexisting apps with the new betas have been receiving this error and aren’t sure what to do about it. Thanks to many folks around the Internet, here we give you solution to resolve your problem:

Add Exception for Domain

To add exception for a single domain, add these keys to your Info.plist. Note that Xcode doesn’t currently auto-complete these keys (as the time of this writing):

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSExceptionDomains</key>
  <dict>
    <key>yourserver.com</key>
    <dict>
      <!--Include to allow subdomains-->
      <key>NSIncludesSubdomains</key>
      <true/>
      <!--Include to allow HTTP requests-->
      <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
      <true/>
      <!--Include to specify minimum TLS version-->
      <key>NSTemporaryExceptionMinimumTLSVersion</key>
      <string>TLSv1.1</string>
    </dict>
  </dict>
</dict>

There are other keys that you can use to configure App Transport Security as well, such as:

NSRequiresCertificateTransparency
NSTemporaryExceptionRequiresForwardSecrecy
NSTemporaryThirdPartyExceptionAllowsInsecureHTTPLoads
NSTemporaryThirdPartyExceptionMinimumTLSVersion
NSTemporaryThirdPartyExceptionRequiresForwardSecrecy

When the Apple documentation is updated, you should familiarize yourself with these other keys and how they’re used. Also, note that some of these keys were listen incorrectly in the “Privacy and Your App” session at WWDC 2015 (NSExceptionAllowsInsecureHTTPLoads instead of NSTemporaryExceptionAllowsInsecureHTTPLoads, for instance). The keys listed above are the correct ones.

Add Exception for Everything

If your app needs to load arbitrary content, Apple provides a way to disable ATS altogether:

<key>NSAppTransportSecurity</key>
<dict>
  <!--Include to allow all connections (DANGER)-->
  <key>NSAllowsArbitraryLoads</key>
  <true/>
</dict>

Thanks to Steven Peterson. Images are from Apple.