3

Our app is working fine on both our production and development environments but on our staging environment we get the common error:

NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)

From my understanding this error occurs when you try to connect to a non https URL.

  • We use ngrok for our local tunnel which has a https url and works fine.
  • For production we also use https://ourdomain.com and it works fine.
  • For staging we use https://staging.ourdomain.comand the error occurs.

I've seen many solutions stating to do this:

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

But my employer is against the idea of disabling ATS just to get staging to work, he is also against the idea of adding an exception for our staging URL.

Any ideas why our staging URL would be causing this error to throw or how to fix it?

ATS Diagnostic output:

Starting ATS Diagnostics

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

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

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

Allowing Arbitrary Loads

---
Allow All Loads
ATS Dictionary:
{
    NSAllowsArbitraryLoads = true;
}
Result : PASS
---

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

Configuring TLS exceptions for staging.domain.co

---
TLSv1.2
ATS Dictionary:
{
    NSExceptionDomains =     {
        "staging.domain.co" =         {
            NSExceptionMinimumTLSVersion = "TLSv1.2";
        };
    };
}
Result : PASS
---

---
TLSv1.1
ATS Dictionary:
{
    NSExceptionDomains =     {
        "staging.domain.co" =         {
            NSExceptionMinimumTLSVersion = "TLSv1.1";
        };
    };
}
Result : PASS
---

---
TLSv1.0
ATS Dictionary:
{
    NSExceptionDomains =     {
        "staging.domain.co" =         {
            NSExceptionMinimumTLSVersion = "TLSv1.0";
        };
    };
}
Result : PASS
---

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

Configuring PFS exceptions for staging.domain.co

---
Disabling Perfect Forward Secrecy
ATS Dictionary:
{
    NSExceptionDomains =     {
        "staging.domain.co" =         {
            NSExceptionRequiresForwardSecrecy = false;
        };
    };
}
Result : PASS
---

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

Configuring PFS exceptions and allowing insecure HTTP for staging.domain.co

---
Disabling Perfect Forward Secrecy and Allowing Insecure HTTP
ATS Dictionary:
{
    NSExceptionDomains =     {
        "staging.domain.co" =         {
            NSExceptionAllowsInsecureHTTPLoads = true;
            NSExceptionRequiresForwardSecrecy = false;
        };
    };
}
Result : PASS
---

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

Configuring TLS exceptions with PFS disabled for staging.domain.co

---
TLSv1.2 with PFS disabled
ATS Dictionary:
{
    NSExceptionDomains =     {
        "staging.domain.co" =         {
            NSExceptionMinimumTLSVersion = "TLSv1.2";
            NSExceptionRequiresForwardSecrecy = false;
        };
    };
}
Result : PASS
---

---
TLSv1.1 with PFS disabled
ATS Dictionary:
{
    NSExceptionDomains =     {
        "staging.domain.co" =         {
            NSExceptionMinimumTLSVersion = "TLSv1.1";
            NSExceptionRequiresForwardSecrecy = false;
        };
    };
}
Result : PASS
---

---
TLSv1.0 with PFS disabled
ATS Dictionary:
{
    NSExceptionDomains =     {
        "staging.domain.co" =         {
            NSExceptionMinimumTLSVersion = "TLSv1.0";
            NSExceptionRequiresForwardSecrecy = false;
        };
    };
}
Result : PASS
---

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

Configuring TLS exceptions with PFS disabled and insecure HTTP allowed for staging.domain.co

---
TLSv1.2 with PFS disabled and insecure HTTP allowed
ATS Dictionary:
{
    NSExceptionDomains =     {
        "staging.domain.co" =         {
            NSExceptionAllowsInsecureHTTPLoads = true;
            NSExceptionMinimumTLSVersion = "TLSv1.2";
            NSExceptionRequiresForwardSecrecy = false;
        };
    };
}
Result : PASS
---

---
TLSv1.1 with PFS disabled and insecure HTTP allowed
ATS Dictionary:
{
    NSExceptionDomains =     {
        "staging.domain.co" =         {
            NSExceptionAllowsInsecureHTTPLoads = true;
            NSExceptionMinimumTLSVersion = "TLSv1.1";
            NSExceptionRequiresForwardSecrecy = false;
        };
    };
}
Result : PASS
---

---
TLSv1.0 with PFS disabled and insecure HTTP allowed
ATS Dictionary:
{
    NSExceptionDomains =     {
        "staging.domain.co" =         {
            NSExceptionAllowsInsecureHTTPLoads = true;
            NSExceptionMinimumTLSVersion = "TLSv1.0";
            NSExceptionRequiresForwardSecrecy = false;
        };
    };
}
Result : PASS
---

================================================================================
Deekor
  • 9,144
  • 16
  • 69
  • 121

1 Answers1

9

App Transport Security is not just HTTP vs HTTPS. You need to be using properly configured servers+certificates to avoid an ATS issue. From the Apple docs [1]:

The server must support at least Transport Layer Security (TLS) protocol version 1.2. Connection ciphers are limited to those that provide forward secrecy. Certificates must be signed using a SHA256 or greater signature hash algorithm, with either a 2048 bit or greater RSA key or a 256 bit or greater Elliptic-Curve (ECC) key. Invalid certificates result in a hard failure and no connection.

If you're on OS X 10.11 (or later), you can use nscurl to troubleshoot. Pop open a terminal and run this:

/usr/bin/nscurl --ats-diagnostics https://staging.ourdomain.com

[1] https://developer.apple.com/library/ios/technotes/App-Transport-Security-Technote/index.html

Ryan LaNeve
  • 1,214
  • 1
  • 10
  • 15
  • Can you paste in the output from nscurl so we can take a look? Might want to add on the "--verbose" switch while you're at it. – Ryan LaNeve Oct 20 '15 at 17:34
  • Hmm...the very first test passing - the "Default ATS Secure Connection" - should be an indicator that your server is correctly configured; that you should not run into an ATS problem. Having said that, I guess it is possible that nscurl is not a sufficient test. I'll be surprised if it's not, but it is possible. Can you try the SSL Labs site to check your staging server? Its output will be more comprehensive regarding how your server is configured. https://www.ssllabs.com/ssltest/index.html Also, have you tried the NSAllowArbitraryLoads key, and did it resolve the problem? – Ryan LaNeve Oct 20 '15 at 19:46
  • I have not tried the arbitrary load. Ive presented that solution to my manager but he doesn't like the idea of circumventing a problem even if its in staging. – Deekor Oct 20 '15 at 20:52
  • I agree with your manager. However, for the purposes of troubleshooting this issue, I'm suggesting you make the change to turn on the NSAllowArbitraryLoads **just** to see if it works. You can revert the change immediately after. If it works, then you have an ATS problem. If it doesn't work, then you don't have an ATS problem. Your results from nscurl suggest you do not have an ATS problem. – Ryan LaNeve Oct 20 '15 at 21:00