I am receiving "This application requires a valid client certificate" message when doing an HTTP GET request using Swift for an iOS app. I am using an iPad iOS 13 for testing and when opening Safari I get a popup to select a client certificate and the server authenticates successfully.
I tried first using a WKWebView and implemented the case where the authentication method is of type NSURLAuthenticationMethodClientCertificate by following Apple's developer documentation and forums:
optional func webView(_ webView: WKWebView,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
But after retrieving the Distinguished Names, I queried for an identity so I can create the Credential and was unable to find one. I assume this is mostly because client certificates are accessible from Apple apps like Safari and Mail but not from my iOS app.
I then tried to use a SFSafariViewController but after I learned that I can't see the website's data after the user authenticates with the client certificate. This is from Apple's documentation:
The user's activity and interaction with SFSafariViewController are not visible to your app, which cannot access AutoFill data, browsing history, or website data.
So, with this option I was unable to transfer request data back to the iOS app.
Finally, I tried using ASWebAuthenticationSession using https://developer.apple.com/documentation/authenticationservices/authenticating_a_user_through_a_web_service. This opened Safari, the user can select their certificate and the web server authenticates. I got a successful callback URL on the iOS app and the Safari view gets dismissed automatically. After the session has been started, I used the following to open a URL:
UIApplication.shared.open(url, options: [:], completionHandler: nil)
It opens the specified url using Safari without requesting the user to be authenticated again. This tells me the ASWebAuthenticationSession was successful. However, I am unable to send this data back to the iOS app. When using a URLSession to do an HTTP request, I get the message that it needs a valid certificate.
I am hoping there is a way from an iOS app to prompt the user for the client certificate (it can be using Safari) and then be able to do HTTP requests after the user has been authenticated on the web server. Is there a way to achieve this without having the .p12 file imported on the keychain? Any suggestions would be appreciated. Thanks!