Cap-go / capacitor-inappbrowser

Capacitor plugin in app browser with urlChangeEvent
MIT License
57 stars 37 forks source link

iOS and Android page stays blank when opening a website with a self-signed certificate using `openWebView` #122

Closed wilomgfx closed 1 month ago

wilomgfx commented 2 months ago

I am able to load a webpage from a server that uses self-signed certificates on Android just fine without any modifications when using .open on Android.

InAppBrowser.openWebView does not work on Android for me. On iOS both .open and .openWebView do not work at all, it seems like they share mostly the same code, so it makes sense.

It's probably related to the SSL certificates being invalid for the webView.

I have to support self-signed certificates for our in-house on prem servers.

On iOS

I can see in the console the following error:

0x10900c818 - [pageProxyID=17, webPageID=18, PID=34768] 
WebPageProxy::didFailProvisionalLoadForFrame: frameID=1, isMainFrame=1, domain=NSURLErrorDomain, 
code=-1202, isMainFrame=1, willInternallyHandleFailure=0

On Android

I can see in Logcat

Failed to validate the certificate chain, error: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
[ERROR:ssl_client_socket_impl.cc(992)] handshake failed; returned -1, SSL error code 1, net_error -202

Which lead me to these SO questions

Working fixes

On iOS

The first step is adding NSAllowsArbitraryLoads , but that alone is enough to make it work it seems.

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>

I was able to make it work by changing this part of the code by using this answer's solution https://stackoverflow.com/a/67500403/2880747

Like so

public func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {

        if let bypassedSSLHosts = bypassedSSLHosts, bypassedSSLHosts.contains(challenge.protectionSpace.host) {
            let credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
            completionHandler(.useCredential, credential)
        } else {
            // code taken from https://stackoverflow.com/a/67500403/2880747
            guard let serverTrust = challenge.protectionSpace.serverTrust  else {
                    completionHandler(.useCredential, nil)
                    return
                }
                let credential = URLCredential(trust: serverTrust)
                completionHandler(.useCredential, credential)
        }
    }

On android

in setWebViewClient inside WebViewDialog https://github.com/Cap-go/capacitor-inappbrowser/blob/a14ce5c572c04b4f3a27c212bef71577fa7618f5/android/src/main/java/ee/forgr/capacitor_inappbrowser/WebViewDialog.java#L322

  @Override
        public void onReceivedSslError(WebView view, SslErrorHandler handler,
                                       SslError error) {
          handler.proceed();
        }

I can make a PR to implement the changes, but if there is a better way, please let me know 😄.

P.S I have 0 experience in Swift/iOS development and just enough in Android, I'm merely hacking my way around these issues to make our PWA (React) wrapped with Capacitor work properly.

DavidHenri008 commented 1 month ago

Any update about this?