7

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.

Community
  • 1
  • 1
Velarion
  • 147
  • 1
  • 10

0 Answers0