iPhone and SSL

by
Tags: , ,
Category:

One of the problems I ran into while working on our iPhone app (see past post) is handling SSL connections. It works just fine with proper certificates, but we have several machines with self-signed SSL certificates. The normal NSURLConnection in the iPhone SDK just rejects connections to a server with a self-signed certificate, and there isn’t an obvious API to get around that.

A few searches turned up a way to override part of NSURLRequest or something like that, but it really seemed to be a hack — plus it seemed to be all-or-nothing, instead of having an easy way to hook into the particulars of each request.

Long story short, I found a better way to handle this, which may be new in the 3.0 SDK. Put this in your NSURLConnection delegate (for asynchronous requests):

>- (BOOL)connection:(NSURLConnection *)connection
canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *) space {
if([[space authenticationMethod]
isEqualToString:NSURLAuthenticationMethodServerTrust]) {
// Note: this is presently only called once per server (or URL?) until
//       you restart the app
if(shouldAllowSelfSignedCert) {
return YES; // Self-signed cert will be accepted
} else {
return NO;  // Self-signed cert will be rejected
}
// Note: it doesn't seem to matter what you return for a proper SSL cert
//       only self-signed certs
}
// If no other authentication is required, return NO for everything else
// Otherwise maybe YES for NSURLAuthenticationMethodDefault and etc.
return NO;
}

Because the delegate typically has more information about the connection, it can make a more intelligent decision in that method. For instance, our app has a config screen where you enter a server URL, username and password if needed, and a checkbox for whether to allow self-signed SSL certificates. So our code above looks up the value of that config setting for the server when the method is called with NSURLAuthenticationMethodServerTrust.

As the comment indicates, the method is only called with NSURLAuthenticationMethodServerTrust once for any given server configuration and the result apparently cached (even across brand new NSURLConnection instances). I’d be interested if there was some way to force it to reset all that and call the method again with NSURLAuthenticationMethodServerTrust.

In a future post, we’ll look at how to support HTTPS client cert authentication, which also seems to have better options in the 3.0 SDK.