[英]Using Client SSL Certificate from .mobileconfig within Enterprise iOS app
We're trying to use Client SSL certificates for user authentication in an enterprise iOS app.我们正在尝试在企业 iOS 应用程序中使用客户端 SSL 证书进行用户身份验证。
How do we get this to work?我们如何让它发挥作用? Thanks!
谢谢!
Overview:概述:
You have installed the Client SSL Certificate on the device keychain.您已在设备钥匙串上安装了客户端 SSL 证书。
Safari.app and Mail.app has access to this keychain while the iOS app doesn't. Safari.app 和 Mail.app 可以访问此钥匙串,而 iOS 应用程序则不能。
The reason is the apps that we develop are sandboxed and doesn't have any access rights outside of it in the non-jailbroken device.原因是我们开发的应用程序是沙盒的,在非越狱设备中没有任何访问权限。
As safari has access to it,it had no trouble connecting and authenticating against the server challenge.由于 safari 可以访问它,因此连接和验证服务器挑战没有问题。
Solution:解决方案:
Include the exported P12 file with the App bundle and refer to it to find the correct client certificate the server was looking for.It is actually a workaround.将导出的 P12 文件包含在 App 包中,并参考它以找到服务器正在寻找的正确客户端证书。这实际上是一种解决方法。 The hardcoding is the reliable way to grab the P12 file.
硬编码是获取 P12 文件的可靠方法。
Implementation:执行:
Method in question is willSendRequestForAuthenticationChallenge
in NSURLConenction delegate
.有问题的方法是
NSURLConenction delegate
willSendRequestForAuthenticationChallenge
。 You need to account for NSURLAuthenticationMethodClientCertificate
challenge type inorder to handle the server challenge.您需要考虑
NSURLAuthenticationMethodClientCertificate
质询类型以处理服务器质询。 This is where we implemented the magic to extract the correct certificate identity from the embedded P12 file.这是我们实现从嵌入的 P12 文件中提取正确证书身份的魔法的地方。 Code is below
代码如下
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
if ([challenge previousFailureCount] > 0) {
//this will cause an authentication failure
[[challenge sender] cancelAuthenticationChallenge:challenge];
NSLog(@"Bad Username Or Password");
return;
}
//this is checking the server certificate
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
SecTrustResultType result;
//This takes the serverTrust object and checkes it against your keychain
SecTrustEvaluate(challenge.protectionSpace.serverTrust, &result);
//if we want to ignore invalid server for certificates, we just accept the server
if (kSPAllowInvalidServerCertificates) {
[challenge.sender useCredential:[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] forAuthenticationChallenge: challenge];
return;
} else if(result == kSecTrustResultProceed || result == kSecTrustResultConfirm || result == kSecTrustResultUnspecified) {
//When testing this against a trusted server I got kSecTrustResultUnspecified every time. But the other two match the description of a trusted server
[challenge.sender useCredential:[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] forAuthenticationChallenge: challenge];
return;
}
} else if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodClientCertificate) {
//this handles authenticating the client certificate
/*
What we need to do here is get the certificate and an an identity so we can do this:
NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identity certificates:myCerts persistence:NSURLCredentialPersistencePermanent];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
It's easy to load the certificate using the code in -installCertificate
It's more difficult to get the identity.
We can get it from a .p12 file, but you need a passphrase:
*/
NSString *p12Path = [[BundleManager bundleForCurrentSkin] pathForResource:kP12FileName ofType:@"p12"];
NSData *p12Data = [[NSData alloc] initWithContentsOfFile:p12Path];
CFStringRef password = CFSTR("PASSWORD");
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { password };
CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
CFArrayRef p12Items;
OSStatus result = SecPKCS12Import((CFDataRef)p12Data, optionsDictionary, &p12Items);
if(result == noErr) {
CFDictionaryRef identityDict = CFArrayGetValueAtIndex(p12Items, 0);
SecIdentityRef identityApp =(SecIdentityRef)CFDictionaryGetValue(identityDict,kSecImportItemIdentity);
SecCertificateRef certRef;
SecIdentityCopyCertificate(identityApp, &certRef);
SecCertificateRef certArray[1] = { certRef };
CFArrayRef myCerts = CFArrayCreate(NULL, (void *)certArray, 1, NULL);
CFRelease(certRef);
NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identityApp certificates:(NSArray *)myCerts persistence:NSURLCredentialPersistencePermanent];
CFRelease(myCerts);
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
}
} else if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodDefault || [[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodNTLM) {
// For normal authentication based on username and password. This could be NTLM or Default.
DAVCredentials *cred = _parentSession.credentials;
NSURLCredential *credential = [NSURLCredential credentialWithUser:cred.username password:cred.password persistence:NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
} else {
//If everything fails, we cancel the challenge.
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
}
Reference: Ref1 , Ref2 , Ref3参考: Ref1 , Ref2 , Ref3
Hope this helps希望这可以帮助
I created a package to work with TLS sockets/iOS/Obj-C.我创建了一个包来处理 TLS 套接字/iOS/Obj-C。 I connect it to a node server but it might work with others.
我将它连接到节点服务器,但它可能与其他人一起工作。 More importantly, I have links to important resources regarding creating certificates correctly given the recent iOS 13 TLS restrictions.
更重要的是,鉴于最近的 iOS 13 TLS 限制,我提供了有关正确创建证书的重要资源的链接。 I hope it can be somewhat helpful:
我希望它可以有点帮助:
https://github.com/eamonwhiter73/IOSObjCWebSockets/tree/master https://github.com/eamonwhiter73/IOSObjCWebSockets/tree/master
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.