App Transport Security (ATS) is enabled by default for apps linked against the iOS 9.0 or OS X v10.11 SDKs or later, as indicated by the default Boolean value of NO for the NSAllowsArbitraryLoads key. This key is at the root level of the NSAppTransportSecurity dictionary.
With ATS enabled, HTTP connections must use HTTPS (RFC 2818). Attempts to connect using insecure HTTP fail. ATS employs the Transport Layer Security (TLS) protocol version 1.2 (RFC 5246). For background on secure Internet connections, read HTTPS Server Trust Evaluation.
With the advent of iOS 9, Apple decided that developers should avoid accessing insecure, unencrypted clear text HTTP (http://) resources on the Internet. Today I’ll show you how to access HTTP sites/services in your apps. I’ll explain the special hoops that Apple wants you to jump through just to use HTTP — and help you keep your app from being rejected.
For Apple to assume that anything HTTP is dangerous is a bit overboard as there are legitimate reasons to access a resource via clear text, like downloading an image (clear binary). Grabbing an image won’t reveal information about users’ private lives. A web/REST service that consumes someone’s name and Social Security number is a different story — that info must be encrypted.
Fortunately, Apple has made some accommodations in allowing continued use of HTTP as long as you provide “justification” when submitting your apps.
While I was developing the Xcode companion projects, one in Swift and one in Objective-C, for my posts on “Concurrency in iOS – Grand Central Dispatch (GCD) with Swift 3” and “Concurrency in iOS: serial and concurrent queues in Grand Central Dispatch (GCD) with Swift 3,” I received the following error message:
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.
It completely slipped my mind, but since I’ve been through this before, I knew exactly how to fix the problem. I dealt with this problem when I wrote my first iOS 9.x app which made reference to an Internet URL. But it’s been awhile and I got the error two days ago when I made these calls in Swift and in Objective-C:
let imageView : UIImageView = self.view.viewWithTag(i) as! UIImageView
let imageURL = URL(string: self.imageURLs[i-10])
let imageData = NSData(contentsOf: imageURL!)
NSURL *url = [NSURL URLWithString:stringURL];
NSData *imageData = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:imageData];
If your URLs are HTTP — not HTTPS — you’ll receive this error no matter how you try to access them, whether you’re using NSURLRequest, NSURLSession, NSURLConnection, stringWithContentsOfURL, etc. You can solve the technical aspect of this problem and get your app working easily and immediately.
Go to Project Navigator, click on your project, and then click on your Info.plist file. [control]-click on Info.plist and a context menu will open. Select Open As -> Source Code and paste the NSAppTransportSecurity dictionary key/values block into your Info.plist file as shown below in text and as an image:
See one of my GitHub project’s Info.plist file here.
Run your app and you’ll get no more errors. Remember that Apple considers the solution I’ve shown above as a sledgehammer approach. After all, I’ve granted blanket access to all or “arbitrary” (NSAllowsArbitraryLoads) HTTP URLs. So when developing and submitting apps, you’ll need to take a more measured approach.
For the following discussion, please read Apple’s “Information Property List Key Reference” topic on Cocoa Keys, subtopic on NSAppTransportSecurity, and the entire sub-subsection on App Transport Security (ATS). Apple’s documentation describes this subject clearly and in-depth, so I’m not going to belabor the point.
If you’re going to try to submit an app using the NSAllowsArbitraryLoads sledgehammer approach, you’ll need to provide Apple reviewers with justification. See Apple’s write-up on ATS Configuration Basics where they clearly state that:
If set to YES, disables all ATS restrictions for all network connections, apart from the connections to domains that you configure individually in the optional NSExceptionDomains dictionary. Default value is NO.
Note: Setting this key’s value to YES triggers App Store review and requires justification.
To provide justification to Apple when submitting an app, go into your iTunes Connect record for the app. Go to My Apps -> [Your app name] -> App Store -> Prepare for Submission -> App Review Information -> Notes and type in a carefully crafted set of reasons for the reviewer(s) explaining why you need to use HTTP.
You can take an alternative approach by specifically naming which HTTP URLs you’re going to use in your app. You can use the NSExceptionDomains key as it “Creates a container for one or more domain-specific dictionaries, letting you specify customized, per-domain HTTP connection properties.”
In the final analysis and pragmatically, you should start using HTTPS exclusively, as much as it’s possible. Are you going to fight a company with a market cap of $750 billion plus $250 billion in cash? Don’t ignore Apple’s guidelines, follow them:
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.
Thanks again for joining me. Check back soon for the next tutorial. Please leave a comment if you have questions or feedback.