468

So, the new beta SDK of iOS released last night has "App Transport Security" which encourages developers to use https instead of http. In principle, this is a great idea, and I already use https in our staging/production environments. However, I don't have https set up in my local development environment, when the iOS app is connecting to a web service I'm running on my laptop.

From a bit of playing around this morning, it appears that the URL loading system will, even if you hand it an http URL, decide to use https instead. Does anyone know how to disable this behaviour -- even just for particular URLs?

soulshined
  • 9,612
  • 5
  • 44
  • 79
Graeme Mathieson
  • 5,108
  • 3
  • 17
  • 9
  • See this: http://stackoverflow.com/questions/31254725/transport-security-has-blocked-a-cleartext-http?noredirect=1#comment52543453_31254725 – Jeef Sep 02 '15 at 12:06
  • I just wrote a guide to verify your Webservice for App transport security, that might helpful https://medium.com/@Mrugraj/app-transport-security-b7910c4fc70f – Mrug Sep 18 '15 at 12:04
  • not working for iOS 9.3 – nickalchemist May 06 '16 at 07:33
  • I have noticed something, this question was asked Jun9 but the link that makes this the `duplicate` was Jul6... – 0yeoj Sep 27 '16 at 04:05
  • How to specify IPAddress instead of the domain in NSExceptionDomains? – Code Runner May 14 '21 at 16:11

8 Answers8

730

See Apple’s Info.plist reference for full details (thanks @gnasher729).

You can add exceptions for specific domains in your Info.plist:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>testdomain.com</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <true/>
            <key>NSExceptionMinimumTLSVersion</key>
            <string>TLSv1.2</string>
            <key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
            <false/>
            <key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
            <true/>
            <key>NSThirdPartyExceptionMinimumTLSVersion</key>
            <string>TLSv1.2</string>
            <key>NSRequiresCertificateTransparency</key>
            <false/>
        </dict>
    </dict>
</dict>

All the keys for each excepted domain are optional. The speaker did not elaborate on any of the keys, but I think they’re all reasonably obvious.

(Source: WWDC 2015 session 703, “Privacy and Your App”, 30:18)

You can also ignore all app transport security restrictions with a single key, if your app has a good reason to do so:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

If your app does not have a good reason, you may risk rejection:

Setting NSAllowsArbitraryLoads to true will allow it to work, but Apple was very clear in that they intend to reject apps who use this flag without a specific reason. The main reason to use NSAllowsArbitraryLoads I can think of would be user created content (link sharing, custom web browser, etc). And in this case, Apple still expects you to include exceptions that enforce the ATS for the URLs you are in control of.

If you do need access to specific URLs that are not served over TLS 1.2, you need to write specific exceptions for those domains, not use NSAllowsArbitraryLoads set to yes. You can find more info in the NSURLSesssion WWDC session.

Please be careful in sharing the NSAllowsArbitraryLoads solution. It is not the recommended fix from Apple.

kcharwood (thanks @marco-tolman)

Caina Santos
  • 919
  • 1
  • 9
  • 16
adurdin
  • 1,376
  • 1
  • 10
  • 15
  • `NSExceptionDomains` should be the preferred approach to selectively remove individual domains – Wain Jun 09 '15 at 13:16
  • 5
    Note that CFNetwork.framework uses different strings than presented in the session for most of these keys, in beta 1: `NSTemporaryExceptionAllowsInsecureHTTPLoads`, `NSTemporaryExceptionMinimumTLSVersion`, `NSTemporaryExceptionRequiresForwardSecrecy`, `NSTemporaryThirdPartyExceptionAllowsInsecureHTTPLoads`, `NSTemporaryThirdPartyExceptionMinimumTLSVersion`, `NSTemporaryThirdPartyExceptionRequiresForwardSecrecy` – adurdin Jun 10 '15 at 15:47
  • 2
    There's now a Technote out at https://developer.apple.com/library/prerelease/ios/technotes/App-Transport-Security-Technote/index.html – gnasher729 Jun 26 '15 at 22:22
  • 11
    What works is `NSIncludesSubdomains` and `NSTemporaryExceptionAllowsInsecureHTTPLoads` to ``. – Cœur Jul 05 '15 at 16:21
  • 28
    The info in this answer didn't work for me. – Jonny Aug 06 '15 at 05:42
  • Thanks @NikYo for pointing out the typo in NSExceptionAllowInsecureHTTPLoads. – adurdin Aug 07 '15 at 12:08
  • 1
    More details in #711 technote : https://developer.apple.com/videos/wwdc/2015/?id=711 – dhar Aug 12 '15 at 15:47
  • Is this working for anyone on xCode 7 beta 6? I am having no luck. Even tried the NSTemporary values. – Alan Scarpa Sep 06 '15 at 18:43
  • 1
    As a side note: IP addresses don't work. In my case I wanted to exclude my development server machine (on local network) by IP... this did not work. I added an alias to the hosts file and used the alias. For example `devpc` instead of `192.168.1.99`. Then add `devpc` into the `NSExceptionDomains` – Lukas Sep 17 '15 at 09:18
  • 1
    Heads up: using NSAllowsArbitraryLoads could get your app rejected. See this conversation: https://github.com/AFNetworking/AFNetworking/issues/2779 – Marco Tolman Sep 17 '15 at 15:57
  • I tried your suggestion to no avail please have a look at my question http://stackoverflow.com/questions/32962155/how-to-add-nsexceprtiondomains-to-plist-of-xcode-version-7-0-1 thanks. – Jack Oct 09 '15 at 04:44
  • @pechar how to do that ? I have 3 IP addresses for my different environemtn (all testing), and all using self-signed HTTPS. I tried every answer in here, but unable to proceed. – HelmiB Oct 19 '15 at 07:32
  • @HelmiB very simple just open your Terminal and type the following `sudo nano /private/etc/hosts` you will be asked for the admin password. Then add the necessary aliases and exit using `Ctrl+X` then pressing 'Y' to confirm save. Then flush the DNS cache using `dscacheutil -flushcache; sudo killall -HUP mDNSResponder` – Lukas Oct 19 '15 at 10:31
  • 2
    This will not work in iOS 10 after december 2016 any more. Your apps must not have these keys in your info.plist, otherwise your apps are going to reject from app store. – Abuzar Amin Aug 02 '16 at 10:16
  • @AbuzarAmin comment about being rejected is not correct. – visc Jun 21 '19 at 18:13
114

As accepted answer has provided required info, and for more info about using and disabling App Transport Security one can find more on this.

For Per-Domain Exceptions add these to the Info.plist:

<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>

But What If I Don’t Know All the Insecure Domains I Need to Use? Use following key in your Info.plist

<key>NSAppTransportSecurity</key>
<dict>
  <!--Include to allow all connections (DANGER)-->
  <key>NSAllowsArbitraryLoads</key>
      <true/>
</dict>

For more detail you can get from this link.

Akshay Sunderwani
  • 12,428
  • 8
  • 29
  • 52
  • The best answer that provides an example of simple settings. – KoCMoHaBTa Sep 28 '15 at 19:08
  • 14
    It doesn't work if using IP Address. can anyone help me to exclude IP address instead of domain name ? – HelmiB Oct 19 '15 at 07:57
  • 4
    just wanted to say, that the domain should be enter WITHOUT "http://" at the beginning – Matias Elorriaga Oct 27 '15 at 20:33
  • this creates a high risk for App rejection As Apple is very clear in that they intend to reject apps who use this flag without a specific reason. The main reason to use NSAllowsArbitraryLoads& created content (link sharing, custom web browser, etc). And in this case, Apple still expects you to include exceptions that enforce the ATS for the URLs you are in control of. – Ash Jul 07 '16 at 16:14
  • 1
    This will not work in iOS 10 after december 2016 any more. Your apps must not have these keys in your info.plist, otherwise your apps are going to reject from app store. – Abuzar Amin Aug 02 '16 at 10:16
  • @HelmiB for IP address try adding .xip.io to the end of the address and put xip.io in your NSExceptionDomains (http://xip.io) – tpankake Oct 13 '16 at 17:23
  • @AbuzarAmin Is there any alternative for adding **Exception Domains** in **App Transport Security Settings** in iOS 10 and later? – AtWork Jan 18 '17 at 17:54
  • @AtWork you can still add exception Domains in App Transport Security Settings but you must have some strong reason for this otherwise App Store will Reject your App.If you have enterprise Application then you don't have to worry about this at all. – Abuzar Amin Feb 17 '17 at 09:40
  • @AbuzarAmin **Exception Domains** no more works for iOS 10 and later. Using only **NSAllowsArbitraryLoads** to **Yes** works for iOS 10 and later. – AtWork Feb 17 '17 at 17:51
  • Provided link doesn't work – Omar Reis Oct 02 '18 at 18:32
61

Followed this.

I have solved it with adding some key in info.plist. The steps I followed are:

  1. Opened my Projects info.plist file

  2. Added a Key called NSAppTransportSecurity as a Dictionary.

  3. Added a Subkey called NSAllowsArbitraryLoads as Boolean and set its value to YES as like following image. enter image description here

Clean the Project and Now Everything is Running fine as like before.

Ref Link.

Community
  • 1
  • 1
Manab Kumar Mal
  • 20,788
  • 5
  • 31
  • 43
  • 2
    This helped me a lot during testing of an app where a SSL cert was not available. – Ripwinder Mar 14 '16 at 16:46
  • 4
    This will not work in iOS 10 after december 2016 any more. Your apps must not have these keys in your info.plist, otherwise your apps are going to reject from app store. – Abuzar Amin Aug 02 '16 at 10:16
37

If you just want to disable App Transport Policy for local dev servers then the following solutions work well. It's useful when you're unable, or it's impractical, to set up HTTPS (e.g. when using the Google App Engine dev server).

As others have said though, ATP should definitely not be turned off for production apps.

1) Use a different plist for Debug

Copy your Plist file and NSAllowsArbitraryLoads. Use this Plist for debugging.

XCode Debug

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

2) Exclude local servers

Alternatively, you can use a single plist file and exclude specific servers. However, it doesn't look like you can exclude IP 4 addresses so you might need to use the server name instead (found in System Preferences -> Sharing, or configured in your local DNS).

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>server.local</key>
        <dict/>
        <key>NSExceptionAllowsInsecureHTTPLoads</key>
        <true/>
    </dict>
</dict>
Community
  • 1
  • 1
Ian
  • 7,480
  • 2
  • 47
  • 51
  • 1
    I would strongly advise against option 1 because it could hide issues that will bite you in your production app (for example, if you are using 3rd party non-secure domains). – Ned Feb 05 '16 at 18:28
  • 3
    I appreciate the feedback but, personally, I don't really think that deserves a down vote. I'm not saying it's the recommended solution. I'm just offering a different option. Obviously, I would recommend excluding specific domains (if HTTPS isn't available) but kcharwood has already given that answer. In any case, I'll leave it up to you. Just thought I'd give my reasoning. – Ian Feb 05 '16 at 18:39
  • 1
    Understood. This seems like the kind of issue beginners may search about, see the suggestion to allow arbitrary loads, and follow without thinking about any consequences. With the solution to allow arbitrary loads for any app release, it's up to Apple to reject the app. Having different settings for different build configurations could lead to someone having the app working during development, but the archived build could be broken. I'm unable to remove my downvote, but if you edit the answer with some potential pitfalls of option 1 I'd be happy to un-downvote it. – Ned Feb 05 '16 at 22:23
31

I have solved as plist file.

  1. Add a NSAppTransportSecurity : Dictionary.
  2. Add Subkey named " NSAllowsArbitraryLoads " as Boolean : YES

enter image description here

Avinash651
  • 1,399
  • 11
  • 17
  • 1
    This will not work in iOS 10 after december 2016 any more. Your apps must not have these keys in your info.plist, otherwise your apps are going to reject from app store. – Abuzar Amin Aug 02 '16 at 10:28
  • then what should we do from ios 10 ?? – N Kaushik Nov 16 '16 at 09:22
  • You shall not use HTTP anymore. If you don't have a choice, use the method in the answer, with `NSExceptionDomains` – Zoleas Nov 25 '16 at 14:27
  • @AbuzarAmin where you did read about this? I'm using the same approach in one of my app and that app is working fine. what's the alternative way to achieve this on iOS 10 and above? – Suryakant Sharma Jan 06 '17 at 05:55
  • @Suryakant it was announced in WWDC videos. If your app is on App Store then it will create problem when you submit your app to App Store for review. – Abuzar Amin Jan 09 '17 at 17:24
  • @AbuzarAmin but untill your app have strong reason to use that key, I read somewhere – Suryakant Sharma Jan 10 '17 at 12:22
  • yup if you can justify to Apple that why are you using it , then there will be no problem. – Abuzar Amin Jan 10 '17 at 12:58
23

Configurations above didn't work for me. I tried a lot of combinations of keys, this one work fine:

enter image description here

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>mydomain.com</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <false/>
        </dict>
    </dict>
</dict>
Damien Romito
  • 9,801
  • 13
  • 66
  • 84
  • This also worked for me on Appcelerator 4.0.0.GA and xcode7 – Sam Texas Sep 25 '15 at 21:37
  • 5
    I'm trying to allow my app to send http requests to my local rails server at localhost:3000...what would I put in for the domain then? I've tried "localhost", "localhost:3000", http://localhost:3000, etc...any ideas? Thanks for the help in advance! – OOProg Dec 28 '15 at 19:07
  • @OOProg localhost:3000 – Damien Romito Feb 19 '16 at 14:30
  • 1
    @OOProg - just plain old localhost worked for me. Also, you need to be sure that your request url is `http://localhost:3000`. NSURLSession data tasks to localhost:3000 without the preceding "http://" won't work. – kcstricks Mar 13 '16 at 04:10
  • 1
    This will not work in iOS 10 after december 2016 any more. Your apps must not have these keys in your info.plist, otherwise your apps are going to reject from app store. – Abuzar Amin Aug 02 '16 at 10:29
18

Compiling answers given by @adurdin and @User

Add followings to your info.plist & change localhost.com with your corresponding domain name, you can add multiple domains as well:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>localhost.com</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <false/>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <false/>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <true/>
            <key>NSExceptionMinimumTLSVersion</key>
            <string>TLSv1.2</string>
            <key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
            <false/>
            <key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
            <true/>
            <key>NSThirdPartyExceptionMinimumTLSVersion</key>
            <string>TLSv1.2</string>
            <key>NSRequiresCertificateTransparency</key>
            <false/>
        </dict>
    </dict>
</dict>
</plist>

You info.plist must looks like this:

enter image description here

Aqib Mumtaz
  • 4,936
  • 1
  • 36
  • 33
16

Here's what worked for me:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <false/>
    <key>NSExceptionDomains</key>
    <dict>
        <key><!-- your_remote_server.com / localhost --></key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <true/>
        </dict>
    <!-- add more domain here -->
    </dict>
</dict>

I just wanna add this to help others and save some time:

if you are using: CFStreamCreatePairWithSocketToHost. make sure your host is the same with what you have in your .plist or if you have separate domain for socket just add it there.

CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)/*from .plist*/, (unsigned int)port, &readStream, &writeStream);

Hope this is helpful. Cheers. :)

0yeoj
  • 4,500
  • 3
  • 23
  • 41