Apple has always been dedicated to protecting the privacy of its customers. To this end, Apple added App Transport Security to further improve the privacy and security of applications that connect to the web. App Transport Security is enabled by default for every application that is built against the iOS 9 SDK or the macOS 10.11 SDK. Even though it is currently possible to opt out of App Transport Security, Apple plans to require App Transport Security for every build submitted to the App Store starting 1 January 2017.

The idea is simple. App Transport Security blocks every request that is made over HTTP and enforces a number of rules for requests that are made over HTTPS. This is the message you see in the console if your application attempts to make a network request over HTTP.

App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file.

Why did Apple add App Transport Security to iOS and macOS? Can you disable it? Should you disable it? In this tutorial, I answer these questions and I also give you a few tips about adopting App Transport Security in your own applications.

Why App Transport Security?

Apple has made it clear that it takes the privacy of its customers very seriously. Application sandboxing is a clear sign of that commitment. With App Transport Security, Apple takes the next step in securing the data of its customers. To this end, App Transport Security blocks every request that is made over an insecure connection.

HTTP has been around for decades. Why is the protocol suddenly made into an enemy? There is no problem with requests made over HTTP as long as you realize that the data is sent as cleartext. And that is by definition insecure. With App Transport Security, Apple attempts to convince or encourage developers to make their applications more secure by making secure connections the default. And Apple isn't the only company taking this direction.

While it is currently possible to disable App Transport Security, Apple plans to require App Transport Security for every build submitted to the App Store starting 1 January 2017. It is important that you are prepared for this event if your application currently disables App Transport Security.

App Transport Security Requirements

Even if your application makes a request over HTTPS, it is still possible App Transport Security blocks the request. Adopting App Transport Security in an application requires more than switching from HTTP to HTTPS. The web servers your application communicates with also need to conform to the requirements set by App Transport Security. What are those requirements?

  • The web server your application talks to must support version 1.2 or later of the TLS (Transport Layer Security) protocol.
  • The connection ciphers of the domain your application connects to need to provide forward secrecy.
  • The web server's certificates need to be signed with a SHA256 hash algorithm (or better) with a key that meets Apple's security standards.

It goes without saying that invalid certificates always result in the request being blocked by App Transport Security.

App Transport Security doesn't force developers to update or upgrade their server infrastructure. In many scenarios, the developer doesn't even have access to the server infrastructure their applications interact with. That said, App Transport Security does require developers to configure their applications in such a way that its network behavior is transparent. Let me show you how that works.

Configuring App Transport Security

I already mentioned that App Transport Security is enabled by default for every application that is compiled against the iOS 9 SDK or the macOS 10.11 SDK. Fortunately, it is possible to configure or tailor App Transport Security to your application's needs. As a developer, you have four options:

  • comply with App Transport Security
  • comply with App Transport Security and define exceptions
  • opt out of App Transport Security and define exceptions
  • opt out of App Transport Security

Note that the latter two options are not recommended since Apple plans to require App Transport Security at the start of 2017. Apple's message is clear. Plan ahead.

Comply With App Transport Security

If you decide to comply with App Transport Security, your application can only make requests over connections that meet the strict requirements I listed earlier. It is important to carefully test your application to make sure no requests are blocked by App Transport Security.

If you decide to go this route, then you don't need to modify your application's Info.plist. To make it clear that your application adopts App Transport Security, you can add the following snippet to your application's Info.plist.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  ...
  <key>NSAppTransportSecurity</key>
  <dict>
    <key>NSAllowsArbitraryLoads</key>
    <false/>
  </dict>
</dict>
</plist>

Comply With Predefined Exceptions

If, for some reason, your application needs to make requests to web servers that don't meet the App Transport Security requirements, you can define exceptions for those domains. You do this by adding one or more exceptions to the Info.plist of your application.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  ...
  <key>NSAppTransportSecurity</key>
  <dict>
    <key>NSExceptionDomains</key>
    <dict>
      <key>cocoacasts.com.s3.amazonaws.com</key>
      <dict>
        <key>NSExceptionAllowsInsecureHTTPLoads</key>
        <false/>
      </dict>
      <key>cocoacasts.com</key>
      <dict>
        <key>NSIncludesSubdomains</key>
        <true/>
        <key>NSExceptionMinimumTLSVersion</key>
        <string>1.0<string/>
      </dict>
    </dict>
  </dict>
</dict>
</plist>

The above configuration specifies that App Transport Security is enforced with two exceptions. The first exception targets the domain myblog.s3.amazonaws.com, an S3 bucket. It tells App Transport Security that requests made over HTTP are allowed for this domain.

The second exception applies to cocoacasts.com and its subdomains. The exception loosens the requirement for the minimum TSL version, setting it to 1.0 instead of 1.2, the default.

Defining exceptions only works if you know upfront what endpoints your application talks to. If your application includes a web browser, for example, then this is not an option.

You can find more details about which keys to include on Apple's developer website.

Opt Out With Predefined Exceptions

Even if you decide that your application currently cannot comply with the App Transport Security requirements, then it is still possible to make your application partially adopt App Transport Security. You specify that your application allows requests made over insecure connections and define exceptions for predefined domains. For these domains, App Transport Security is in effect. This is interesting if you have control over the domains the exceptions apply to.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  ...
  <key>NSAppTransportSecurity</key>
  <dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>NSExceptionDomains</key>
    <dict>
      <key>cocoacasts.com</key>
      <dict>
        <key>NSAllowsArbitraryLoads</key>
        <false/>
        <key>NSExceptionRequiresForwardSecrecy</key>
        <true/>
        <key>NSExceptionMinimumTLSVersion</key>
        <string>1.2<string/>
      </dict>
    </dict>
  </dict>
</dict>
</plist>

This configuration permits requests made over HTTP with the exception of requests made to cocoacasts.com. Note that you need to specify what the requirements are for the exception domain. In this example, the exception enforces the default requirements of App Transport Security.

Opt Out of App Transport Security

Even though opting out of App Transport Security is simple, you need to be aware that App Transport Security is put in place to make you, the developer, more aware of the security of your application. Only choose this option if there is no other solution and know that your application need to comply with App Transport Security before the end of 2016.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  ...
  <key>NSAppTransportSecurity</key>
  <dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
  </dict>
</dict>
</plist>

Network Behavior

App Transport Security is an exercise for developers to describe the network behavior of their applications. By configuring App Transport Security for an application, the developer needs to carefully consider which web servers the application talks to. This could potentially expose security risks the developer wasn't aware of. No matter what approach you take, it is important to carefully consider the options described in this article.

What's Next?

App Transport Security is something every Cocoa developer needs to deal with. Apple will soon require developers to enable App Transport Security for every build submitted to the App Store. You can read more about App Transport Security on Apple's developer website.

Have you already adopted App Transport Security or did this blog post catch you by surprise? Questions? Leave them in the comments below or reach out to me on Twitter.