You can now create a Persistent Token extension on iOS 14 and implement the TKTokenDriver, TKToken and TKTokenSession objects you need. You put the extension in your app and it will get loaded even if your app has not launched. Apple's own apps will use your extension bu the UI is clumsy. A WKWebView in your own app will use your token, but not automatically. First, you need to add com.apple.token to your entitlements:
<array>
<string>com.apple.token</string>
</array>
You need to have your delegate handle
webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
and when you get challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate you should query for SecIdentities to use:
var keychainItems = [[String:AnyObject]]()
for tokenID in TKTokenWatcher().tokenIDs {
let query : [String:Any] = [kSecClass as String:kSecClassIdentity,
kSecAttrTokenID as String: tokenID,
kSecReturnAttributes as String: true,
kSecReturnRef as String: true,
kSecMatchLimit as String: kSecMatchLimitAll]
var items : CFTypeRef?
status = SecItemCopyMatching(query as CFDictionary, &items)
if status == errSecSuccess && items != nil {
statusOKs += 1
if let found = items as? [[String:AnyObject]] {
for item in found {
keychainItems.append(item)
}
}
}
}
If you have multiple identities, you should display a list for the user to choose from.
Finally make a credential:
let cred = URLCredential(identity: identity, certificates: nil, persistence: .forSession)
and return it through the callback handler from the call to your web view delegate.