Using NSURLSession with NSURLCredentialStorage and NSURLAuthenticationMethodClientCertificate

1.9k views Asked by At

I am trying to avoid using

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler

I know you can store credentials in the

NSURLCredentialStorage * credentialStorage = [NSURLCredentialStorage sharedCredentialStorage];

I am storing my client cert in the credential storage using the following code

// Create Credential Store
NSURLCredentialStorage * credentialStore = [NSURLCredentialStorage sharedCredentialStorage];

// Create Configuration
NSURLSessionConfiguration * sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
[sessionConfiguration setURLCredentialStorage:credentialStore];

// Create Session
NSURLSession * session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:self delegateQueue:self.delegateOperationQueue];

// Create Credential
SecCertificateRef myCertificate;
SecIdentityCopyCertificate(request.clientIdentity, &myCertificate);
const void * certs[] = { myCertificate };
CFArrayRef certsArray = CFArrayCreate(NULL, certs, 1, NULL);
NSURLCredential * credential = [NSURLCredential credentialWithIdentity:request.clientIdentity certificates:(__bridge NSArray*)certsArray persistence:NSURLCredentialPersistencePermanent];
CFRelease(certsArray);

// Create Protection Space
NSString * host = [urlRequest.URL host];
NSInteger port = [[urlRequest.URL port] integerValue];
NSString * protocol = [urlRequest.URL scheme];
NSURLProtectionSpace * protectionSpace = [[NSURLProtectionSpace alloc] initWithHost:host port:port protocol:protocol realm:nil authenticationMethod:NSURLAuthenticationMethodClientCertificate];

// Add Credential to Shared Credentials
[credentialStorage setDefaultCredential:credential forProtectionSpace:protectionSpace];

Once I have added it here the Session/Task does not read it from the store. I implemented the

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler

method and was able to recieve the challenge this way and I am able to get the default credential by doing the following

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler

{
    if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodClientCertificate)
    {
        NSString * host = [[challenge protectionSpace] host];
        NSInteger port = [[challenge protectionSpace] port];
        NSString * protocol = [[challenge protectionSpace] protocol];

        NSLog(@"%@ %ld %@",host,(long)port,protocol);

        // Get Credential
        NSURLCredential * credential = [[NSURLCredentialStorage sharedCredentialStorage] defaultCredentialForProtectionSpace:[challenge protectionSpace]];
    }

    // Defualt Handling
    completionHandler(NSURLSessionAuthChallengePerformDefaultHandling,nil);
}

Which means to me that the credential is stored correctly but when I tell the completion handler to perform the default handling it fails and this is the error I get.

2014-11-03 11:09:02.368 PCSRegistrationServer Application[5555:1507600] CFNetwork SSLHandshake failed (-9824 -> -9829)

2014-11-03 11:09:02.459 PCSRegistrationServer Application[5555:1507600] NSURLConnection/CFURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9829)

Am I thinking about this wrong or is NSURLCredentialStorage not for NSURLAuthenticationMethodClientCertificate

0

There are 0 answers