Client Certificate Handling on iOS

Marco Eidinger
Nerd For Tech
Published in
2 min readMar 5, 2022

Client Certificate Authentication, a.k.a. mutual certificate-based authentication, means that the client provides its Client Certificate to the server to prove its identity. This happens as a part of the SSL Handshake ( optional).

Users can install digital identities (certificates plus their associated private keys) onto their iOS devices by downloading them from within Safari, by opening them as email attachments, and by installing them with configuration profiles (MDM!).

Once done the SafariViewController or the Safari app can open the page successfully because the certificate is in the Apple keychain access group.

BUT your apps using URLSession or WKWebView will receive an HTTP 400 response because of a missing client certificate ?!?!

That’s because …

Apps can only access keychain items in their own keychain access groups. This means that items in the Apple access group are only available to Apple-provided apps such as Safari or Mail.

The solution is

… you will need to write code to import them. This typically means reading in a PKCS#12-formatted blob and then importing the contents of the blob into the app’s keychain using the function SecPKCS12Import documented in Certificate, Key, and Trust Services Reference.

This way, your new keychain items are created with your app’s keychain access group.

This statement comes from Apple.

Additional work is needed.

I created an iOS application to demonstrate all this better. Use this app to access client.badssl.com in various ways

  • URLSession.dataTask
  • WKWebView
  • SFSafariViewController
  • Open link in Safari

The website requires a valid user certificate. Otherwise the server returns HTTP 400.

I added badssl.com-client.p12 (downloaded from badssl.com/download) as a bundle resource for convenience. This allows you to test the successful authentication with a user certificate using URLSession and WKWebView.

Note: If the certificate no longer works (expires Dec 4, 2023), try to download the latest version from badssl.com/download.

The source code of the app is publicly available on GitHub.

Originally published at https://blog.eidinger.info.

--

--

Marco Eidinger
Nerd For Tech

Software Engineer open-source and enterprise mobile SDKs for iOS and macOS developers | @MarcoEidinger on Twitter | visit blog.eidinger.info