androidsslandroid-webviewclient-certificates

Method onReceivedClientCertRequest in Android WebViewClient is called only once


I am trying a two-way mTls authentication on Android using WebView. I installed my client certificate in the Android Keychain and I overrode the method onReceivedClientCertRequest as below to obtain the client cert from the Android Keychain:

@Override
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void onReceivedClientCertRequest(WebView view, ClientCertRequest request) {
    Log.d("MC-999","onReceivedClientCertRequest");
    Log.d("MC-999", request.getHost());
    Log.d("MC-999", request.getPrincipals()[0].getName());
    ((WebViewActivity) mContext).selectClientCert(request);
}


@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void selectClientCert(ClientCertRequest request) {
    Log.d("MC-999","Select client cert.");
    mRequest = request;
    KeyChain.choosePrivateKeyAlias(this,
        this, // Callback
        request.getKeyTypes(), 
        request.getPrincipals(), // issuers.
        request.getHost(), // host
        request.getPort(), // port
        "");
}

@Override
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public void alias(@Nullable String alias) {
    if (alias != null) {
        X509Certificate[] certChain = getCertificateChain(alias);
        PrivateKey privateKey = getPrivateKey(alias);
        mRequest.proceed(privateKey, certChain);
    } else {
        mRequest.ignore();
    }
}

Issue: The method onReceivedClientCertRequest is called only once, the first time. It is not called thereafter. I have to reboot the device to ensure that the client cert is requested again. The documentation also states that

"Webview stores the response in memory (for the life of the application) if ClientCertRequest#proceed or ClientCertRequest#cancel is called and does not call onReceivedClientCertRequest() again for the same host and port pair."

My problem is that if the user chooses the wrong cert the first time, the WebView continuous to use it thereafter. The method mWebView.clearSslPreferences(); doesn't seem to clear the sslContext.

Is there a way to forget the user's certificate choice in case I encounter an SSL error?


Solution

  • Just use WebView.clearClientCertPreferences method. It's static method. I faced the same problem as you and this method works fine for me!