In iOS 9, Apple introduced "App Transport Security," or ATS. This defaults apps to requiring an HTTPS connection, and returning an error for non-HTTPS connections. In addition, HTTPS connections must also be using the latest protocol, Transport Layer Security (TLS) v1.2 and will fail to establish a connection if an older version is being used by the web server. In addition, there are hardened encryption standards that are expected that sometimes go beyond the standard TLS v1.2 implementation.
With modern web services, there is no reason to send data in the clear. Thanks to SSL session reuse, performance should no longer be a concern. All data should be sent over SSL.
These new defaults are useful for countering "leaks." While your may have moved all your REST API endpoints to HTTPS, they may reference insecure resources, such as image assets.
Unfortunately, you may have to connect to APIs outside of your control which do not offer HTTPS.
You can poke holes in ATS by adding a
NSAppTransportSecurity dictionary to Info.plist. Add an
NSExceptionDomains dictionary to whitelist specific domains. It may resemble:
You may also use
NSAllowsArbitraryLoads to completely disable ATS in your app:
Or in XML:
<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key><true/> </dict>
This is strongly discouraged. Only use this during development.
Starting in iOS 10, Apple provided a few
.plist keys that can be used to narrow down the exceptions you include to ATS's strict security. Instead of using
NSAllowsArbitraryLoads by itself, you can also now use a few keys that override this key's behavior. Quoting the Apple doc on the topic:
In iOS 10 and later, and macOS 10.12 and later, the value of [
NSAllowsArbitraryLoads] is ignored—resulting in an effective value for this key of its default value of NO—if any of the following keys are [also] present in your app’s Info.plist file:
Here's a quick table of what each key is used for. The Apple doc has more complete information on each key, if you need more information.
||An optional Boolean value that, when set to
||Set this key’s value to
||An optional Boolean value that, when set to
The keys that require justification will trigger an App Store review. The Apple doc lists some valid reasons you can submit, just search for
justificationon the doc - if you're using third party SDKs, one valid reason is that your app "must connect to a server managed by another entity that does not support secure connections".
Using any of these keys will effectively cancel out the blanket effects of the
NSAllowsArbitraryLoads key on iOS 10+ devices. This seems great, since many users of these special keys may only want exceptions for downloaded videos, user-controlled web browsing, advertisement browser redirects, or other use cases. However, users of multiple third-party SDKs should be careful: If any third-party SDK requests that you use the
NSAllowsArbitraryLoads key by itself, then you can't include any of these more specific keys in your
.plist. Otherwise, you may break some functionality in the SDK that required the
NSAllowsArbitraryLoads key by itself, since it may be relying on the effects of that key outside of web views, media playback, and/or local networking.
You can test out issues with App Transport Security by using the
nscurl --ats-diagnostics <URL>
The results will show you whether default connections will fail, and whether using using older versions of Transport Layer Security (TLS) or disabling options such as Perfect Forward Secrecy (PFS) will resolve the issue. For instance, you may need to modify
Info.plist to include downgrading TLS versions or disabling PFS options:
<key>mywebsite.com</key> <dict> <key>NSExceptionAllowsInsecureHTTPLoads</key> <false/> <key>NSTemporaryExceptionMinimumTLSVersion</key> <string>1.0</string> <key>NSTemporaryExceptionRequiresForwardSecrecy</key> <false/> </dict>
Troubleshooting ATS-related issues can be difficult to do. The error codes you see in the XCode device logs are the first place to check. Next, if this information is insufficient, you may need to examine via packet tracing since these network protocols operate at a lower level than HTTP.
The different CFError codes such as -9800 are defined in Apple's open source code. You can review these error codes to see if there is an obvious error.
First, connect an iPhone to the USB port of a Mac. Next, get the current list of interfaces:
$ ifconfig -l lo0 gif0 stf0 en0 en1 p2p0 fw0 ppp0 utun0
Open iTunes on the Mac. Click on the icon for the iPhone device.
Click the Serial number text to display the UDID. Record the UDID by using Ctrl-Click to copy the UDID.
Then run the tool with the UDID of the device:
$ rvictl -s <UDID>
You should see: Starting device <UDID [SUCCEEDED]
Get the list of interfaces again, and you can see the new virtual network interface, rvi0, added by the previous command:
$ ifconfig -l lo0 gif0 stf0 en0 en1 p2p0 fw0 ppp0 utun0 rvi0
You can then use WireShark to capture network traffic on the
ATS requires strict encryption ciphers. You can use the Chrome Security tab (
Developer Tools) to check what encryption standard is used:
Make sure web sites must implement strong encryption ciphers that implement perfect forward secrecy. Here is the current list that iOS10 devices will support (in order of preference):
If you are trying to test an internal site, the
nmap tool can also be used to extract the encryption ciphers that a web site supports.
brew install nmap nmap --script ssl-enum-ciphers -p 443 <URL>
A report similar to the following will be generated, showing what TLS standards are supported and what encryption ciphers can be used.
Nmap scan report for www.cnn.com (22.214.171.124) Host is up (0.0057s latency). Other addresses for www.cnn.com (not scanned): 126.96.36.199 188.8.131.52 184.108.40.206 2a04:4e42::323 2a04:4e42:200::323 2a04:4e42:400::323 2a04:4e42:600::323 PORT STATE SERVICE 443/tcp open https | ssl-enum-ciphers: | TLSv1.0: | ciphers: | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A | TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A | TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A | TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A | TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C | compressors: | NULL | cipher preference: server | warnings: | 64-bit block cipher 3DES vulnerable to SWEET32 attack | TLSv1.1: | ciphers: | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A | TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A | TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A | TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A | TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C | compressors: | NULL | cipher preference: server | warnings: | 64-bit block cipher 3DES vulnerable to SWEET32 attack | TLSv1.2: | ciphers: | TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (secp256r1) - A | TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (secp256r1) - A | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (secp256r1) - A | TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (secp256r1) - A | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (secp256r1) - A | TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (secp256r1) - A | TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A | TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A | TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A | TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C | compressors: | NULL | cipher preference: server | warnings: | 64-bit block cipher 3DES vulnerable to SWEET32 attack |_ least strength: C Nmap done: 1 IP address (1 host up) scanned in 0.97 seconds
In addition, there are public sites such as https://apptransport.info and ssllabs.com/ssltest/analyze.html that allow you to check whether public web sites are ATS-compatible. For apptransportinfo, Simply add the URL at the end (i.e. https://apptransport.info/www.codepath.com) to run the test.