I am trying to connect from UIWebView to a server that uses a self-signed certificate via https using Swift 3. I installed the certificate on my iOS device and I can connect to the server using Safari on iOS, so the problem is in the application.
The best approach I found is described here using Objective-C:
UIWebView for viewing self-signed sites (no private api, not NSURLConnection) - is this possible?
I tried to translate it in 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 this: it never receives the URLAuthenticationChallenge (or sends a request for it) - this way it does not work. I added both the "canAuthenticateAgainstProtectionSpace protectionSpace" and the "willSendRequestFor challenge: URLAuthenticationChallenge" methods - I know that canAuthenticateAgainstProtectionSpace will not be called when using willSendRequestFor. It does not work, no matter what function I delete.
Does anyone have an idea how to solve this problem with Swift 3? Any help would be greatly appreciated.