42

I'm trying to connect my iOS app to an HTTPS Rails app which is currently run on a local host in my network. I can access the site from my browser with https://myIP:3000/display as well as in the command line with a curl request. I'm trying to access it from my app using:

class FirstViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        //let url = NSURL(string: "https://another/Sinatra/website/feed")
        let url = NSURL(string: "https://myIP:3000/display")

        let request = NSURLRequest(URL: url!)
        let task = NSURLSession.sharedSession().dataTaskWithURL(url!)
        task!.resume()
    }

When I try to access the sinatra website I have no trouble and can even print out the JSON to the console with the correct commands. However, when I set url to my Rails website I get the following error.

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

In addition, I can tell that my localhost Rails app (on the other machine) is not pinged from the iOS app, but is pinged from the browser and curl command.

Any ideas how to fix this?

Eric Aya
  • 68,765
  • 33
  • 165
  • 232
Marcus
  • 7,523
  • 9
  • 39
  • 79
  • Put your code in `viewWillDisplay` or `viewDidDisplay`. `viewDidLoad` is to early for most things. – zaph Jun 11 '15 at 21:06
  • Which iOS and Swift version? Add that information to the question. – zaph Jun 11 '15 at 21:07
  • possible duplicate of [CFNetwork SSLHandshake failed iOS 9 Beta 1](http://stackoverflow.com/questions/30720813/cfnetwork-sslhandshake-failed-ios-9-beta-1) – Andrei Jun 12 '15 at 13:40
  • 1
    possible duplicate of [NSURLSession/NSURLConnection HTTP load failed](http://stackoverflow.com/questions/30739473/nsurlsession-nsurlconnection-http-load-failed) – Tariq Jun 15 '15 at 11:20
  • Also happens in Objective C (not only on swift) – Daniel Benedykt Sep 21 '15 at 14:26

7 Answers7

42

If I understood well, Apple now wants the developers to use HTTPS and TLS 1.2 for network calls.

Temporary, you can add this in your "Info.plist" file :

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

Just have a look to this link, it may also help you : http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/

--

Update : Following some comments the above solution is not anymore working. Here is an updated solution.

  1. Go to your Info.plist file.
  2. Add a row of Type Dictionary and of Key App Transport Security Settings.
  3. In this Dictionary, add a row of Type Boolean, of Key Allow Arbitrary Loads and of Value YES

-

Otherwise you can set Domain Exceptions. This is how to do :

  1. Go to your Info.plist file.
  2. Add a row of Type Dictionary and of Key App Transport Security Settings.
  3. Add a row of Type Dictionary and of Key Exception Domains.
  4. Add a row of Type Dictionary and of Key The domain.
  5. Add two rows of Type Boolean and of Key NSExceptionAllowsInsecureHTTPLoads & NSIncludesSubdomains with Value to YES.

Links

https://forums.developer.apple.com/message/5857#5857

2015 WWDC Session 711

iOS 9 HTTP Connection Error - StackOverflow

Antoine
  • 1,091
  • 9
  • 20
20

This is a trust issue. With a self-signed certificate, the identity verification component of SSL does not work. It's still possible to establish a secure connection so that nobody is eavesdropping, but the app cannot be sure of who is on the other end of the line.

I have a similar setup, and solved this issue by adding my self-signed root CA to the iPad trusted certificates. This root CA is used to sign all of my other development certificates. Then I just have to add this single root certificate anywhere that SSL will be used. If you just have a self-signed certificate that you are using directly, you can probably just add that.

To get the certificate onto the device (or simulator), I put the file on my web server. Then just open it in Safari over plain HTTP. The Settings app should open and ask if you want to trust the certificate.

Of course this is assuming that this is for development only, and that your production system has a certificate signed by a well-known authority (i.e. one included in the OS' database of root certificate authorities). Because asking end users to install your self-signed certificate won't fly.

Brian
  • 15,450
  • 4
  • 44
  • 62
6

This is the only solution worked for me... At the end of your AppDelegate.m file, insert the code:

@implementation NSURLRequest(DataController)
+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString *)host
{
return YES;
}
@end

Thanks for jc ivancevich article http://ivancevich.me/articles/ignoring-invalid-ssl-certificates-on-cordova-android-ios/

Anton P
  • 61
  • 1
  • 3
1

(Edit - I misread this as 9814, expired cert. I'm not sure how to solve this one, but hopefully my response helps point in the right direction.)

Looks like a cert issue different from the usual "Allow Arbitrary Loads" question.

Brief excerpt from: Apple Documentation - Appendix A: Common Server Trust Evaluation Errors

NSOSStatusErrorDomain errSSLNoRootCert -9813

1

try change the session variable, this change help me

let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
0

Modifying the info.plist worked for me as well.

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

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

Add a new row in your plist file.enter image description here

svkumar
  • 67
  • 7