I'm trying to open my website https://beta.truckerdistrict.com in a react native app and it's giving me a white screen without any error or alerts in UI. I tested https://facebook.com and other and all is working fine. Checking logs I found the following error:
Failed to validate the certificate chain, error: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found
Here is my webview code, it's really simple without anything special:
<WebView
ref={this.WEBVIEW_REF}
userAgent={this.USER_AGENT}
javaScriptEnabled={true}
uploadEnabledAndroid={true}
allowUniversalAccessFromFileURLs={true}
mixedContentMode="always"
onNavigationStateChange={this._onNavigationStateChange}
onLoadEnd={this._onLoadEnd}
onError={this._onLoadError}
onMessage={this._onWebMessage}
source={{uri: this.BASE_URL}}
The reason why the webview fail to load the url is the SSL certificate. when the webview fail to validate an ssl ceriticate it throws an exception
(error: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.)
then the method
onReceivedSslError(WebView view, SslErrorHandler handler, SslError error)
is called if not @overrided by default the processing of the url is canceled otherwise if implemented we have different types of ssl errors that comes in SsError object we should force the processing of the url by calling handler.process
see bellow the implementation and the cases that u should handle also u can debug and understand what the real matter with ur URL ssl certificate:
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler,
SslError error) {
switch (error.getPrimaryError()) {
case SslError.SSL_UNTRUSTED:
LogUtility.debug("SslError : The certificate authority is not trusted.");
break;
case SslError.SSL_EXPIRED:
LogUtility.debug("SslError : The certificate has expired.");
break;
case SslError.SSL_IDMISMATCH:
LogUtility.debug("The certificate Hostname mismatch.");
break;
case SslError.SSL_NOTYETVALID:
LogUtility.debug("The certificate is not yet valid.");
break;
}
handler.proceed();
}
Please note also that, sometimes an app is not published to the PlayStore because of this, cause we should provide a popup message with a yes or no to let the user decide if he agree to open the url even if there's an ssl certificate issue or no.
I don't know but there should be a way to force the process of validation of the ssh certificate from the web
If you're using an Android 7.0/6/5/4 device (API 24 or below), and your website uses 'Let's Encrypt' SSL certificates to gain HTTPS support for URLs, these devices will no longer trust the Let's Encrypt certificates, starting from 1 September 2021. You will start seeing errors like this in WebViews
that load HTTPS pages:
I/X509Util: Failed to validate the certificate chain, error: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
or
javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
If you use onReceivedSslError()
in your WebView
, it will trigger the case of SslError.SSL_UNTRUSTED
Android 7.1 (API 25) and above is not affected.
Possible workarounds are to fallback to HTTP on these old devices, or change the certificate service on your web backend service. Another potential workaround is to use Firefox web browser on the old devices, because Firefox does trust Let's Encrypt.
Sources:
Sometimes its because your root ca certificate is not chained as part of the server certificate.
Simply add the ca.crt right after the server.crt (in the same file)
Webview is sensitive for that, yet chrome desktop is not...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With