Our customers want to use an MDM (mobile device management) solution (MobileIron) to install client certificates onto corporate iOS devices, in order to limit access to certain corporate web services to corporate devices only.
MobileIron installs the client certificate into Settings > General > Profiles, which is the default location for certificates in iOS, and Safari can respond with this certificate when a corporate web service challenges it for one.
But I need the same thing to happen from within a custom app. When our app gets challenged for a certificate, I need to be able to respond with the certificate from Settings > General > Profiles. I have examples of responding with a certificate which is bundled with our app, and with a certificate which our app stores within its own keychain, but I do not have an example of responding with a certificate installed on the device in Settings > General > Profiles.
Can anyone explain to me more about what the NSURLAuthenticationChallengeSender
protocol method -performDefaultHandlingForAuthenticationChallenge:
does? Does default handling mean that iOS effectively responds to the challenge on behalf of the app? Can this response include a client certificate stored in Settings > General > Profiles?
Update
If the MDM could install a client certificate into the app keychain, that would be perfect.
I just came back from an onsite at a customer who was using MobileIron and was looking to do just this. MobileIron development support provided us with this snippet of code, which imports a certificate provided by the AppConnect Wrapper through MobileIron's Core Config technology.
It's not pretty, but as it was provided by them I was not allowed to modify it. It works though! You insert this into your AppDelegate.h:
And this into your AppDelegate.m, right after the aforemention pragma mark:
Once you've built your app, ask the MobileIron administrator to 'wrap' the app so that it can use AppConnect. Once that is done and the wrapped app is deployed to test users via MobileIron, set up a Core Config that take a User Certificate specific for the provisioned user and pushes it to the provisioned devices under the Core Config key "kUserCert".
Apple tech support pointed me to the following tech note in response:
https://developer.apple.com/library/ios/qa/qa1745/_index.html
To summarise, what we want to do is not supported.
MobileIron's AppConnect 2.1 update solves this problem, no special code required. X.509 certificates can be pushed with the AppConnect Configuration, and the AppConnect framework intercepts any authentication challenges when it can respond with an eligible cert. Certs can be created on-the-fly at first launch, revoked later, customized per-user or per-device, and different URL's can use different certs.
If anyone is using the code snippet on this page, stop, it's not needed. After wrapping your unmodified app, or linking-in the AppConnect framework, add an MI_AC_CLIENT_CERT_1 key to your AppConnect Configuration, pointing to a Certificate Enrollment configuration (i.e. SCEP, Entrust, Symantec PKI, PIV-D, etc.). Add a MI_AC_CLIENT_1_RULE key with a URL (with optional wildcard). There is no step 3. Your app will now automatically use certs for authentication.
Full details are in MobileIron's AppConnect and AppTunnel Guide docs, under "Certificate authentication from AppConnect apps to enterprise services".