Handling Let's encrypt new certificates in WebView for Android M and older

Viewed 923

Android apps, running on devices with Android M or older, that use WebView to display web content may experience breakages from Jan 2021 as Let's Encrypt will start issuing certificates signed with their new certificate chain in 2021

Read https://letsencrypt.org/2020/11/06/own-two-feet.html for background.

1 Answers

First, to know if you app will have an issue, try to open https://valid-isrgrootx1.letsencrypt.org/ on Android devices with M and older.

The solution for WebViews has two parts:

API >= 24

Add the Let's Encrypt root certificates (X1 and X2) to the network_security_config.xml file.

<network-security-config>
    <base-config cleartextTrafficPermitted="true" >
        <trust-anchors>
            <certificates src="@raw/isrg_root_x1" />
            <certificates src="@raw/isrg_root_x2" />
            <certificates src="system" />
        </trust-anchors>
    </base-config>
</network-security-config>

Then add the network security config to your Android manifest

<manifest...>
  <application
      ...
      android:networkSecurityConfig="@xml/network_security_config"
      ...
  </application>
</manifest>

API < 24

For older devices Android does not have public API to add certificates to its trust manager and so the validation will have to be done manually.

  • override onReceivedSslError in your WebView client
  • upon SSL_UNTRUSTED error perform a chan validation manually
    override fun onReceivedSslError(view: WebView?, handler: SslErrorHandler, error: SslError) {
        var trusted = false
        when (error.primaryError) {
            SSL_UNTRUSTED -> {
                // manual validation
                trusted = validateSslCertificateChain(error.certificate)
            }
            else -> ...
        }

        if (trusted) handler.proceed() else super.onReceivedSslError(view, handler, error)
    }

The function validateSslCertificateChain is the one that will manually perform the chain validation. It can be done in several ways. An example can be found in this PR for DuckDuckGo browser.

Also see this other SO question for solutions in other Android networking areas.

Related