Thursday, July 15, 2010

How to Accept Self-Signed Server Certificate

We have public server, test server and release test server. Likewise I generate three different binaries, each connecting to different server. The problem is that test servers have self-signed certificates and iPhone fails by default in NSURLConnection sendSynchronousRequest. The error note is:

ERROR CODE -1202 = The certificate for this server is invalid. You might be connecting to a server that is pretending to be “xx.xx.xxx.xxx” which could put your confidential information at risk.
The solution with iOS4 is this one line:
#if (defined(TEST_VERSION) || defined(RELEASE_TEST_VERSION))
    [NSURLRequest setAllowsAnyHTTPSCertificate:YES
                                       forHost:[url host]];
#endif
    [NSURLConnection sendSynchronousRequest:request 
                          returningResponse:&response
                                      error:&error];
Please note that the specific line is undocumented class method and thus not used in official release, only for testing with simulator or ad hoc releases.

To remove compiler warning add this at the beginning of your file:
#if (defined(TEST_VERSION) || defined(RELEASE_TEST_VERSION))
@interface NSURLRequest (DummyInterface)
+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString*)host;
+ (void)setAllowsAnyHTTPSCertificate:(BOOL)allow forHost:(NSString*)host;
@end
#endif
More info at Dr. Touch article: Ignoring Certificate Errors on NSUrlRequest.

iOS5 update: this code might (or maybe not) help a little from my blog article Server API change from HTTP to HTTPS

6 comments:

  1. Grrrrrrrr... searching for a solution to this issue I keep finding this stupid solution which apple will not accept because it uses a private method. I really wish people would stop posting and reposting this.

    ReplyDelete
  2. Well, I did write it's undocumented and not to be used in official release. However the code is good during development and while waiting for the real certificate.

    ReplyDelete
  3. Thanks so much! But in my case, it only works on ios 5.

    Do you know how make it work on ios 4?

    ReplyDelete
  4. Well, I used it exactly like that in iOS4. Actually for iOS5 I had to use a bit different (documented and legal) method.

    ReplyDelete
  5. Thank you very much. This different (documented and legal) method you mentioned, can you explain what you did? If not, can you point me in the right direction?

    Thanks again

    ReplyDelete
  6. For iOS5 please check NSURLConnectionDelegate method willSendRequestForAuthenticationChallenge (and connectionShouldUseCredentialStorage)

    ReplyDelete