Engineering

Developing for iOS9 App Transport Security

Since iOS 9, Apple has introduced a new feature called App Transport Security (ATS). This enforces your app to communicate with the outside world using HTTPS only.

App Transport Security is good

ATS is good for you, and your app’s users. It forces you, as an app developer to use secure endpoints only, thereby protecting the information exchanged between your app’s user, and your own service.

That being said, you can disable ATS completely, or just for a single domain. Since disabling it completely is generally a very, very bad idea, I’ll not mention how to do so.

Disabling ATS for a single domain

While ATS is a strong requirement, it might hinder your app’s development – mainly because you’d want your app to connect to a service running on your WiFi network, which most likely wouldn’t support TLS. A situation like this can easily be identified when you see the following exception:


2016-03-20 16:26:07.408 MyApp[3252:1920618] 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.

or


Error : Error Domain=NSURLErrorDomain Code=-1022 "The resource could not be loaded because the App Transport Security policy requires the use of a secure connection." UserInfo={NSUnderlyingError=0x7fae7846f7d0 {Error Domain=kCFErrorDomainCFNetwork Code=-1022 "(null)"}, NSErrorFailingURLStringKey=http://aws.amazon.com/s3/, NSErrorFailingURLKey=http://aws.amazon.com/s3/, NSLocalizedDescription=The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.}

To quickly overcome this situation, you could add your host to your app’s Info.plist (as directed by the exception itself):


<!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>a.com</key>
                <dict>
                    <key>NSIncludesSubdomains</key>
                    <true />
                    <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
                    <true />
                </dict>
            </dict>
        </dict>
        ...
        ...
    </dict>
</plist>

Note: Adding the above exception for a domain in your app’s Info.plist mustn’t be taken lightly. It exposes potential security vulnerabilities to your user’s data.

Testing your domain for ATS compliance

Just before releasing your app, you’d want to ensure that all the endpoints your app connects to are ATS compliant, using the nifty nscurl tool (available on your Mac):


ms2:~ jude$ /usr/bin/nscurl --ats-diagnostics --verbose https://api.clevertap.com
Starting ATS Diagnostics

Configuring ATS Info.plist keys and displaying the result of HTTPS loads to https://api.clevertap.com.
A test will "PASS" if URLSession:task:didCompleteWithError: returns a nil error.
================================================================================

Default ATS Secure Connection
---
ATS Default Connection
ATS Dictionary:
{
}
Result : PASS
---

================================================================================

What you’re expecting in the above is a “PASS” for the default ATS setting.

Dealing with domains beyond your control

Often, your app would probably rely on another service, which may or may not be ATS compliant. Using nscurl can help you decide which exceptions (if at all required) are necessary for that particular domain.

Further reading

 

,

4000

55 billion

1 billion

10 billion