Hi all, Nice to meet you, this is my first post! In the past, i developed an OpenSSL engine in order to use my custom crypto token for RSA signatures. I used such engine in Linux Qt WebView widget (based on Webkit) in order to authenticate to HTTPS using client certificate and private key contained into the token. I'd like to do the same in iOS, is it possible with WKWebView? Or with some keychain API? Thanks P
RSA key for web client authentication
is it possible with WKWebView?
Not on iOS. On macOS you can publish your crypto token via the CryptoTokenKit and it will be used by all system services including
WKWebView
and the Safari app. iOS does not support this, alas. Your only option right now is use
UIWebView
. This lets you
intercept the underlying HTTPS requests, allowing you to run those requests with your own TLS. This is
not fun.
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"
Hi Thank you very much for the answer. Do you have a sample code or just a snippet ? F
Do you have a sample code … ?
My previous post had a link to the CustomHTTPProtocol sample code.
IMPORTANT This sample demonstrates intercepting
NSURLAuthenticationMethodServerTrust
authentication challenges, which is a bit pointless these days because the support in
WKWebView
for those challenges works just fine. However, it should be relatively straightforward to adapt it to intercept
NSURLAuthenticationMethodClientCertificate
authentication challenges.
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"
I apologize,
I saw the code and i didn't understant how to modify it for my purpose.
When you wrote i have to use my own TLS, you mean that i have to manage all the handshake and encryption and decryption with the agreed chipersuite ?
Thanks.
P
I saw the code and i didn't understant how to modify it for my purpose.
OK. I believe I’ve confused you here, and I apologise for that. Earlier I wrote:
However, it should be relatively straightforward to adapt it to intercept
authentication challenges.NSURLAuthenticationMethodClientCertificate
which is true but irrelevant to your requirements. The custom
NSURLProtocol
technique will let you see all the requests made by the
UIWebView
. A lot of developers just want to handle client identity authentication challenges using the built-in networking stack, and the technique shown by
CustomHTTPProtocol can be readily adapted for that. However, that’s not possible in your case.
The sticking point is that the TLS in the built-in networking stack uses the built-in security stack for its crypto operations. There’s no ability for you to plug your hardware token in to this stack (on iOS; on macOS you can do this using CryptoTokenKit). Thus, not only do you need to implement the crypto primitives, you need to implement:
TLS on top of that
HTTP on top of that
This, as I said earlier, is not fun.
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"
First of all, thank you for your support, I finally came to a custom NSURLProtocol solution to handle my needs. Now I have to switch to WKWebview due to Apple restriction on apps update from December 2020.
I sadly didn't find anything similar to a custom protocol in WKWebview, there is only the WKURLSchemeHandler but it doesn't allow to handle http or https in a custom way. Is there another way or other objects to use with WKWebview that allow me to switch from UIWebview to WKWebview and (possibly) reuse my custom NSURLProtocol?
Is there another way or other objects to use with
that allow me to switch fromWKWebview
toUIWebview
and (possibly) reuse my customWKWebview
?NSURLProtocol
Sadly, the ability to intercept all the network traffic generated by the web view is one of the missing pieces in
WKWebView
right now.
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"
And what about CryptoTokenKit? By documentation it seems possible to use it on ios 13.0+
In one of your previous replies Re: RSA key for web client authentication you said that maybe is possible to use CryptoTokenKit and WKWebView to achieve in our goal. Is now possible on iOS as it seems?
And what about CryptoTokenKit?
I’d expect this to work just fine on macOS. I discussed this issue with DTS’s CryptoTokenKit specialist just last week and my understanding, based on that conversation, is that third-party CryptoTokenKit extensions are not currently supported on iOS.
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"
Code Block <key>keychain-access-groups</key> <array> <string>com.apple.token</string> </array>
You need to have your delegate handle Code Block 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:Code Block 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:
Code Block let cred = URLCredential(identity: identity, certificates: nil, persistence: .forSession)
and return it through the callback handler from the call to your web view delegate.