func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
var error: CFError?
if #available(iOS 12.0, *) {
dispatch_semaphore_t sema = dispatch_semaphore_create(0); // Multiple requests may come to load into web view
self.pinningCompletion = completionHandler; // strong property
DebugLog(tag: TAG, info: "WebView: didReceive challenge - ios12 or higher")
if let trust = challenge.protectionSpace.serverTrust, !SecTrustEvaluateWithError(trust, &error) {
// OK
let ok = UIAlertAction(title: "OK", style: .default) { _ in
let exceptions = SecTrustCopyExceptions(trust)
SecTrustSetExceptions(trust, exceptions)
completionHandler(.useCredential, URLCredential(trust: trust))
dispatch_semaphore_signal(sema);// on completion of alert action
}
// Cancel
let cancel = UIAlertAction(title: "Cancel", style: .cancel) { _ in
completionHandler(.cancelAuthenticationChallenge, nil)
dispatch_semaphore_signal(sema);// on completion of alert action
}
// Show prompt
let message = error!.localizedDescription + "\nDo you want to continue?"
let alert = UIAlertController(title: "SSL Error", message: message, preferredStyle: .alert)
alert.addAction(ok)
alert.addAction(cancel)
DispatchQueue.main.async {
self.present(alert, animated: true, completion: nil)
}
if (![NSThread isMainThread]) {
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
} else {
while (dispatch_semaphore_wait(sema, DISPATCH_TIME_NOW)) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0]];
}
}
}
else {
let cred = URLCredential(trust: challenge.protectionSpace.serverTrust!)
completionHandler(.useCredential, cred)
}
} else {
DebugLog(tag: TAG, info: "WebView: didReceive challenge - fallback older versions")
let cred = URLCredential(trust: challenge.protectionSpace.serverTrust!)
completionHandler(.useCredential, cred)
}
}