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.
- URLSession:
URLSessionDelegate
is required which implementsURLSession:didReceiveChallenge:completionHandler:
and returnsURLCredential
instance to resolve a client certificate authentication challenge. - WKWebView:
WKNavigationDelegate
is required which implementswebView(_:didReceive:completionHandler:)
and returnsURLCredential
instance to resolve a client certificate authentication challenge.
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.