# Client Certificate Handling on iOS

**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*).

![How Mutal Authentication Works](https://www.thesslstore.com/blog/wp-content/uploads/2021/05/how-mutual-authentication-works.png)

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](https://developer.apple.com/documentation/security/1396915-secpkcs12import).

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

This [statement](https://developer.apple.com/library/archive/qa/qa1745/_index.html) comes from Apple.

**Additional work is needed**.

- **URLSession**: `URLSessionDelegate` is required which implements [`URLSession:didReceiveChallenge:completionHandler:`](https://developer.apple.com/documentation/foundation/nsurlsessiondelegate/1409308-urlsession) and returns [`URLCredential`](https://developer.apple.com/documentation/foundation/urlcredential/1418121-init) instance to resolve a client certificate authentication challenge.
- **WKWebView**: `WKNavigationDelegate` is required which implements [`webView(_:didReceive:completionHandler:)`](https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455638-webview) and returns [`URLCredential`](https://developer.apple.com/documentation/foundation/urlcredential/1418121-init) instance to resolve a client certificate authentication challenge.

I created an iOS application to demonstrate all this better. Use this app to access  https://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.

%[https://youtu.be/qSzk-gMsFZ4]

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

%[https://github.com/MarcoEidinger/ClientCertificateSwiftDemo]



