18

I've created an iOS app using Cordova 3.2 and jquery mobile 1.3. I use jquery ajax to send requests to a RESTfull service to retrieve/update information.

I have a number of test devices, various iPhones, with various different iOS versions. On an iPhone 4S, running iOS 7 I receive the following error when any ajax request is sent:

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

This only happens on this device, on another iPhone 4S, also running iOS 7, it works absolutely fine, as it does on all of the other test devices I'm using.

I've read that this indicates the certificate is invalid in someway, that being the case, can this be ignored and why would affect on one device?

Can anyone suggest why this might be happening and what could be different about the device that would prevent it from working only on one of my devices. Thanks

Martin Cassidy
  • 686
  • 1
  • 9
  • 28

5 Answers5

33

I had a similar issue, but in my case, across all devices this used to happen and only during an ajax call with https.

If that is your case, adding the below code at the end of appDelegate.m file will mitigate your issue.

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

But i do doubt that if it is working in other devices, the solution i have given, might not be effective. But do give it a try.

Vikram
  • 479
  • 1
  • 4
  • 14
  • 9
    Very useful for testing purposes (I just set up a clone of our production server to repro an issue, and it obviously uses a different domain than our real site, so its SSL cert is not valid). NEVER EVER DO THIS IN PRODUCTION CODE, though - it's as good as not using SSL. – Arkaaito Jan 20 '14 at 22:42
  • I did think about trying this, but have read that Apple would reject the app if I used it, so wouldn't really solve the problem – Martin Cassidy Jan 22 '14 at 10:30
  • I got an app approved with this code, but isn't a good idea to use it, as Arkaait says, using this is as not using SSL at all. – jcesarmobile Feb 20 '14 at 08:13
  • 1
    This worked for me on Cordova 3.0. I needed it to hit some dev servers that have self signed certs. As others have said, do not use in production!!!! – JimTheDev May 02 '14 at 01:50
  • That code should get rejected by Apple, if found. Anyway, worked for me in dev with Cordova 3 + iOS 9.2, thanks! – Papasmile Mar 16 '16 at 01:53
  • omg, Mark.. Thank you very much.. I spend about 2 days.. to find solution. your answer help me. lol – S.J. Lim Apr 10 '17 at 10:33
12

If it's working on some devices and not others, there's some difference in the certificate validation parameters for those devices. Here are some things to look at:

  1. Do the happy devices have some root certificate that the unhappy devices don't? Particularly if they are running different iOS versions, they may have different lists of trusted certificates as well. Try going to Settings > General > About and compare the numbers for "Trust Store" at the very bottom. See more info here.
  2. Did you manually accept some intermediate certificate (used to sign this certificate) on the happy devices at some point in the past?*
  3. Is the date/time wrong on the unhappy device? If it's set to a time after the certificate expiry date or before the certificate issue date, it will reject it. I'm always shooting myself in the foot with this one!

If you access your endpoint URL in the browser on the unhappy device, what error does it give you? (Note: obviously your server will give you some error as well because you aren't requesting with the right headers and params. I'm talking about Safari itself, though - it should give a more detailed message about what (it thinks) is wrong with the certificate.)

*Edited to correct something I misremembered: you do not have the option to accept the leaf certificate if you go to the URL in Safari, you only have the option to accept intermediate certificates if you attempt to load them directly.

Arkaaito
  • 7,347
  • 3
  • 39
  • 56
  • The problem actually was a missing intermediate cert on the server side. Once this corrected, all the devices became "happy". I think one of your first two points must have been the case (I did reset happy and unhappy devices to factory defaults though and they still did the same thing) – Martin Cassidy Jan 22 '14 at 10:30
  • @MartinCassidy how did you go about generating a missing intermediate cert on the server side? I too am testing using a self-signed cert in Apache and am getting the same error code - works on desktop but not on iPhone 5S – user1361529 Jun 25 '15 at 14:53
  • @user1361529 it wasn't me that did it, the server admin sorted it out. It wasn't a self signed cert. Sorry I can't be of more help. – Martin Cassidy Jun 26 '15 at 15:19
2

The Swift version of Markivs answer (taken from here):

extension NSURLRequest {
    static func allowsAnyHTTPSCertificateForHost(host: String) -> Bool {
        return true
    }
}
Community
  • 1
  • 1
Chris
  • 489
  • 5
  • 15
2

Xcode 7.3 Swift 2.2

To get this to work I had to do 3 things:

  1. I had to add Chris's answer^ to the bottom of the AppDelegate.swift after the closing } for the class
  2. then modify Info.plist using this answer https://stackoverflow.com/a/32701693
  3. Make sure you set a domain name for the server instead of an IP Address
Community
  • 1
  • 1
Brewster
  • 21
  • 3
1

I got the same issue while running the application in simulator .the reason behind this is there is no trusted certificate in the simulator.

simply drag & drop your .cer Files into your running Simulator window. You'll see Safari flashing and then the import dialog for your Certificate (or Certificate Authority)...

user3540599
  • 721
  • 9
  • 6