iOS HTTPS requests 101
Solution 1
Getting the corresponding error description may help:
So, first the error domain kCFStreamErrorDomainSSL
means that the error code is an SSL error code as defined in Security/SecureTransport.h:
kCFStreamErrorDomainSSL, -9813 means:
errSSLNoRootCert = -9813, /* cert chain not verified by root */
And that simply means, you have no trusted root certificate and the connection fails because of that authentication failure.
Provide a root certificate on the device for the server trust authentication and you are fine.
There are a few approaches to implement server trust authentication with self-signed certificates, the one more secure than the other.
The simplest approach requires a self-signed certificate which is stored in the bundle of the app, then retrieved and simply byte-compared. Here is an example:
Implementing server trust authentication with a self-signed certificate.
These are a must read also: Technical Note TN2232 HTTPS Server Trust Evaluation and Technical Q&A QA1360 Describing the kSecTrustResultUnspecified error.
The more preferred approach is to use a CA (Certificate Authority) which you can be yourself. That is, you create your own CA and your certificates signed with this CA.
The steps are similar:
- Bundel the DER file of your CA's root certificate in your app.
-
Handle the server trust authentication as follows:
- get the authentication challenge
- retrieve the trust object from the challenge
- create a certificate object from the data in your bundle
- set the certificate object as an anchor to the trust object using function
SecTrustSetAnchorCertificates
. - evaluate the trust
Solution 2
not sure if this will actually fix the problem, but it may help. you should be using
– connection:willSendRequestForAuthenticationChallenge:
since the other methods are deprecated. take a look at the overview of the NSURLConnectionDelegate protocol
Related videos on Youtube
Nikolay Dyankov
Updated on September 15, 2022Comments
-
Nikolay Dyankov about 1 year
NSURLConnection/CFURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)
Very, very frustrating! I've been pulling my hair for hours with this. I'm using a self-signed certificate on my Linode server. The port is 8000, couldn't get it to work on 443. I don't believe this is the reason though. Here's my code, it's 99% boilerplate:
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.myserver.com:8000/test.json"]]; NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
At the bottom:
#pragma mark NSURLConnectionDelegate - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace { NSLog(@"protectionSpace: %@", [protectionSpace authenticationMethod]); // We only know how to handle NTLM authentication. if([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodNTLM]) return YES; // Explicitly reject ServerTrust. This is occasionally sent by IIS. if([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust]) return NO; return NO; } - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { [[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge]; } - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { NSLog(@"%@", response); } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { NSLog(@"%@", data); } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { NSLog(@"didFailWithError"); NSLog([NSString stringWithFormat:@"Connection failed: %@", [error description]]); }
OMG HELP!
UPDATE
It worked with this delegate method. I'm receiving the response, but there is a problem.
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { [[challenge sender] useCredential:[NSURLCredential credentialWithUser:@"user" password:@"password" persistence:NSURLCredentialPersistencePermanent] forAuthenticationChallenge:challenge]; }
The "user" and "password" that I have provided are completely random and aren't checked by the server. How can I verify the credentials before accepting the connection on my server?
EDIT: I'm running a Node.js server
-
Fonix over 10 yearsunfortunately im a bit of a noob with this authentication stuff, so im not sure
-
cat about 10 yearsHere is the URL for decrypting other error codes ... opensource.apple.com/source/libsecurity_ssl/…