Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Allow unverified ssl certificates in WKWebView

I'm trying to load a HTTPS url with an self-signed certificate in a WKWebView for iOS 8 and it keeps failing. The workaround used with UIWebView (using setAllowsAnyHTTPSCertificate from NSUrlRequest) doesn't seem to work. Does anyone know of any workaround?

I do not need a solution that is valid for AppStore, as I only need to access self-signed certificate sites on development phases, not on production, but it's really a problem for development and testing server instances.

Thank you in advance.

like image 327
Roi Avatar asked Nov 24 '14 08:11

Roi


Video Answer


3 Answers

This is fixed in iOS 9! WKWebView finally makes calls to webView(_:didReceiveAuthenticationChallenge:completionHandler:) on WKNavigationDelegate. Unfortunately this does not work if you run code built in Xcode 7 on iOS 8 devices (at least not in my initial testing).

In my example below, I'm not actually doing anything with the cert and just letting it pass through without doing any further validation (obviously a bad plan for production code). See Apple's docs (Listing 3) for more details of what they want you to do here.

Swift:

func webView(webView: WKWebView, didReceiveAuthenticationChallenge challenge: NSURLAuthenticationChallenge,
    completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
        let cred = NSURLCredential.init(forTrust: challenge.protectionSpace.serverTrust!)
        completionHandler(.UseCredential, cred)
}

Swift 3:

let cred = URLCredential(trust: challenge.protectionSpace.serverTrust!)
completionHandler(.useCredential, cred)

Swift 4:

func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
    let cred = URLCredential(trust: challenge.protectionSpace.serverTrust!)
    completionHandler(.useCredential, cred)
}

Objective-C

NSURLCredential * credential = [[NSURLCredential alloc] initWithTrust:[challenge protectionSpace].serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
like image 91
jvoll Avatar answered Oct 14 '22 15:10

jvoll


I spent a lot of time looking into this, as an ios newbie, none of the solutions proposed were complete in my opinion. So here is what I did to get WKWebView to work in my case (very simple web view that needs access to self signed cert for dev only):

First thing: in my root Info.plist file, I added "App Transport Security Settings" as a dictionary, and add "Allow Arbitrary Loads" item with a value of YES.

App Transport Security Settings Allow Arbitrary Loads

Second: I added this code to my ViewController (inherits UIViewController and WKNavigationDelegate) - this was sourced from several answers elsewhere

func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
    guard let serverTrust = challenge.protectionSpace.serverTrust else { return completionHandler(.useCredential, nil) }
    let exceptions = SecTrustCopyExceptions(serverTrust)
    SecTrustSetExceptions(serverTrust, exceptions)
    completionHandler(.useCredential, URLCredential(trust: serverTrust))
}

NOTE THAT THIS SOLUTION WILL LIKELY BE REJECTED BY THE APP STORE - I WILL SUBMIT TO THE APP STORE WITH "Allow Arbitrary Loads" ITEM WITH A VALUE OF NO.

like image 41
simong5443 Avatar answered Oct 14 '22 16:10

simong5443


I have the same error, and try to solve it using the Most Voted answer above, I used the following code to create a NSURLCredential object, but it failed.

NSURLCredential * credential = [[NSURLCredential alloc] initWithTrust:[challenge protectionSpace].serverTrust];

Then I found a solution in Apple Developer Forums. This helped me :

- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
  NSLog(@"Allow all");
  SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
  CFDataRef exceptions = SecTrustCopyExceptions (serverTrust);
  SecTrustSetExceptions (serverTrust, exceptions);
  CFRelease (exceptions);
  completionHandler (NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:serverTrust]);
  }
like image 31
guozqzzu Avatar answered Oct 14 '22 15:10

guozqzzu