, , , , , ,

Some time ago I blogged about client/server implementation for two way SSL ( both client and server are authenticated with certs ) on top of nodeJS, ( blog post ). Now, I’m trying to connect iOS client to nodeJS HTTPS server.

I will use NSURLConnection for requests. Also, client authentication is only possible with asynchronized requests, simplified sendSynchronousRequest doesn’t support delegates. I will load p12 generated certificate from App resources for authentication ( maybe better idea is to use Keychain for “production” applications but here I just want to test things )

Example Xcode project is available on HttpSSLClient – GitHub

So, when request is made to HTTPS server which requires authentication with certificate delegate’s connection:didReceiveAuthenticationChallenge is called. In this method we need to obtain certificate ( for code simplicity I will load cert each time from resource ) and present it to sender which will use that certificate against server.

Note: I’m playing here with self signed certificates and code didn’t work until I added this ( thanks to guy that found this ). Also, for simplicity I’m returning YES without any validation here.

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
    return YES;

Back on track, to load certificate I’m using:

NSString *path = [[NSBundle mainBundle] pathForResource:@"userA" ofType:@"p12"];
NSData *p12data = [NSData dataWithContentsOfFile:path];
CFDataRef inP12data = (__bridge CFDataRef)p12data;
SecIdentityRef myIdentity;
SecTrustRef myTrust;
OSStatus status = extractIdentityAndTrust(inP12data, &myIdentity, &myTrust);
SecCertificateRef myCertificate;
SecIdentityCopyCertificate(myIdentity, &myCertificate);
const void *certs[] = { myCertificate };
CFArrayRef certsArray = CFArrayCreate(NULL, certs, 1, NULL);

extractIdentityAndTrust function is copied from Apple Certificate, Key, and Trust Services Programming Guide with slightly modifications:

OSStatus extractIdentityAndTrust(CFDataRef inP12data, SecIdentityRef *identity, SecTrustRef *trust)
    OSStatus securityError = errSecSuccess;
    CFStringRef password = CFSTR("userA");
    const void *keys[] = { kSecImportExportPassphrase };
    const void *values[] = { password };
    CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
    CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
    securityError = SecPKCS12Import(inP12data, options, &items);
    if (securityError == 0) {
        CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex(items, 0);
        const void *tempIdentity = NULL;
        tempIdentity = CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemIdentity);
        *identity = (SecIdentityRef)tempIdentity;
        const void *tempTrust = NULL;
        tempTrust = CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemTrust);
        *trust = (SecTrustRef)tempTrust;
    if (options) {
    return securityError;

After certificate is loaded we need NSURLCredential that will be sent to certificate challenger

NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:(__bridge NSArray*)certsArray persistence:NSURLCredentialPersistencePermanent];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];

For debug I’m using nodeJS server and certificate for userA is taken from that Git repo.


NSURLConnection class
Apple URL loading guide
Apple Certificate, Key, and Trust Services Programming Guide
NSURLConnection with Self-Signed Certificates
How to use Client Certificate Authentication in iOS App
How to connect with client certificate using a WebView in Cocoa?