I am trying to connect from an UIWebView to a server which uses a self signed certificate over https using Swift 3. I have installed the certificate on my iOS device and I can connect to the server using Safari on iOS, so the problem lies within the app.
The best approach I have found is described here using Objective C:
UIWebView to view self signed websites (No private api, not NSURLConnection) - is it possible?
I've tried to translate it to Swift 3 as follows:
override func viewDidLoad() {
super.viewDidLoad()
webView.delegate = self
// other stuff
}
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
print("HTTPSSETUP should start load with request: authenticated \(authenticated)")
if(!authenticated) {
print("HTTPSSETUP not yet authenticated - trying")
globalRequest = request
let conn: NSURLConnection = NSURLConnection(request: request, delegate: self)!
conn.start()
return false
}
// some other stuff
return true
}
func connection(_ connection: NSURLConnection, willSendRequestFor challenge: URLAuthenticationChallenge) {
print("HTTPSSETUP In willSendRequestForAuthenticationChallenge..");
challenge.sender!.use(URLCredential(trust: challenge.protectionSpace.serverTrust!),for: challenge)
challenge.sender!.continueWithoutCredential(for: challenge)
}
func connection(_ connection: NSURLConnection, canAuthenticateAgainstProtectionSpace protectionSpace: URLProtectionSpace) -> Bool {
print("HTTPSSETUP can authenticate against protection space")
return true
}
func connection(_ connection: NSURLConnection, didReceive challenge: URLAuthenticationChallenge) {
print("HTTPSSETUP did receive authentication challenge")
if(challenge.previousFailureCount == 0) {
authenticated = true
let credential: URLCredential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
challenge.sender?.use(credential, for: challenge)
} else {
challenge.sender?.cancel(challenge)
}
}
func connection(_ connection: NSURLConnection, didReceive response: URLResponse) {
print("HTTPSSETUP did receive response")
authenticated = true
self.webView.loadRequest(globalRequest)
connection.cancel()
}
func connection(_ connection: NSURLConnection, didFailWithError error: Error) {
print("HTTPSSETUP did fail with error: " + error.localizedDescription)
}
This is the output in the console:
HTTPSSETUP should start load with request: authenticated false
HTTPSSETUP not yet authenticated - trying
2016-12-22 10:35:22.747238 AppName[916:341139] [] nw_coretls_read_one_record tls_handshake_process: [-9824]
2016-12-22 10:35:22.748404 AppName[916:341215] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824)
HTTPSSETUP did fail with error: An SSL error has occurred and a secure connection to the server cannot be made.
So basically - the way I see it - the main problem is the following: It never receives the URLAuthenticationChallenge (or sends the request for it) - thus failing. I have added both the methods "canAuthenticateAgainstProtectionSpace protectionSpace" as well as "willSendRequestFor challenge: URLAuthenticationChallenge" - I know that canAuthenticateAgainstProtectionSpace won't be called when using willSendRequestFor. It does not work, no matter which function I remove.
Does anyone have an idea how to solve this problem using Swift 3? Any help would be greatly appreciated.