Starting from iOS 9, App Transport Security enforces to use secure HTTPS requests by default.
App Transport Security
App Transport Security (ATS) enforces best practices in the secure connections between an app and its back end. ATS prevents accidental disclosure, provides secure default behavior, and is easy to adopt; it is also on by default in iOS 9 and OS X v10.11. 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 addition, your communication through higher-level APIs needs to be encrypted using TLS version 1.2 with forward secrecy. If you try to make a connection that doesn't follow this requirement, an error is thrown. If your app needs to make a request to an insecure domain, you have to specify this domain in your app's Info.plist file.
In short, when an application is compiled with Xcode 7 and iOS 9, and attempt to connect to HTTP server that doesn't support latest SSL technology (TLS 1.2), it 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}
From App Transport Security Technote:
All connections using the NSURLConnection, CFURL, or NSURLSession APIs use App Transport Security default behavior in apps built for iOS 9.0 or later, and OS X 10.11 or later. Connections that do not follow the requirements will fail. For more information on various the connection methods, see NSURLConnection Class Reference, CFURL Reference, or NSURLSession Class Reference.
Fortunately we can specify exceptions from default behavior in Info.plist
. Doing this, we can leverage App Transport Security where possible, while disabling it in places where you cannot support it.
<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>
This is considerably a dangerous approach and should not be used sparingly.
<key>NSAppTransportSecurity</key>
<dict>
<!--Include to allow all connections (DANGER)-->
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
Some things to note:
- Apps built using earlier SDK will behave the same. But if compiled using Xcode 7 onwards, we must migrate.
- For apps using the Facebook SDK, read their guide to adapt changes.
- For a short and more throughout information regarding this, you can read this article.
- For full list of exception keys, check out this table from Apple.
Official documents:
- WWDC 15 - Networking with NSURLSession
- App Transport Security Technote
- [What's New in iOS 9] (https://developer.apple.com/library/prerelease/ios/releasenotes/General/WhatsNewIniOS/Articles/iOS9.html#//apple_ref/doc/uid/TP40016198-SW14)
- iOS 9 Release Notes
- Application Transport Security ? - Apple Developer Forums
- Application Transport Security (ATS) and app submission - Apple Developer Forums
Note from Facebook SDK and Google Ads SDK:
Articles and blogs:
A few notes that I observe
CFNetwork SSLHandshake failed
error will occur, unless we specify to disable this "feature" in Info.plist