I am trying to use NSUrlsession to connect server with SSL (.p12) client certificate. I have connected to same server using NSURLConnection successfully. But with NSURLsession i get "cancelled" error. Following is my setup:
-(void) loadDataFromServer{
NSURL *url=[NSURL URLWithString:@"https://domain:port/serviceName/method/parameter"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLSessionConfiguration *sessionConfig =[NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session=[NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:Nil];
NSURLSessionDataTask *downloadTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSLog(@"Data :%@",data);
NSLog(@"Response :%@",response);
NSLog(@"Error :%@",error);
if (!error) {
NSHTTPURLResponse *httpResp = (NSHTTPURLResponse*) response;
if (httpResp.statusCode == 200) {
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:data
options:kNilOptions
error:&error];
NSLog(@"Data :%@",json);
}
}
}];
[downloadTask resume];}
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * __nullable credential))completionHandler{
NSURLCredential *newCredential;
NSString *authenticationMethod = challenge.protectionSpace.authenticationMethod;
if ([authenticationMethod isEqualToString:@"NSURLAuthenticationMethodServerTrust"]) {
// Replace the user login and password as appropriate.
newCredential = [NSURLCredential credentialWithUser:@"UserName" password:@"Password" persistence:NSURLCredentialPersistenceNone];
} else if ([authenticationMethod isEqualToString:@"NSURLAuthenticationMethodClientCertificate"]) {
// load cert
NSString *path = [[NSBundle mainBundle] pathForResource:@"certificateName" ofType:@"p12"];
NSData *p12data = [NSData dataWithContentsOfFile:path];
CFDataRef inP12data = (__bridge CFDataRef)p12data;
SecIdentityRef myIdentity;
SecTrustRef myTrust;
OSStatus status = extractIdentityAndTrustCorpInv(inP12data, &myIdentity, &myTrust);
if (status == 0) {
SecCertificateRef myCertificate;
SecIdentityCopyCertificate(myIdentity, &myCertificate);
const void *certs[] = { myCertificate };
CFArrayRef certsArray = CFArrayCreate(NULL, certs, 1, NULL);
newCredential = [NSURLCredential credentialWithIdentity:myIdentity certificates:(__bridge NSArray*)certsArray persistence:NSURLCredentialPersistenceForSession];
}
}
[[challenge sender]useCredential:newCredential forAuthenticationChallenge:challenge];
completionHandler(NSURLSessionAuthChallengeUseCredential,newCredential);
}
#pragma mark -
#pragma mark Identity and Trust
- OSStatus extractIdentityAndTrustCorpInv(CFDataRef inP12data, SecIdentityRef *identity, SecTrustRef *trust)
{
OSStatus securityError = errSecSuccess;
CFStringRef password = CFSTR("CertPassword");
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) {
CFRelease(options);
}
return securityError;
}
And NSLog gives following error:
Error :Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLKey=https://domain:port/serviceName/method/parameter, NSErrorFailingURLStringKey=https://domain:port/serviceName/method/parameter, NSLocalizedDescription=cancelled}
Any help would be appreciated .