Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android WebView handle onReceivedClientCertRequest

I'm developing an Android app using Client Certificate Authentication within WebView. The certificate (cert.pfx) and password are embedded in the application.

When executing Client Certificate Authentication request with ajax call in the WebView, the following function getting called :

@Override
public void onReceivedClientCertRequest(WebView view, final ClientCertRequest request) {}

As I understend I need to call :

request.proceed(PrivateKey privateKey, X509Certificate[] chain)

Any idea how to create the PrivateKey and X509Certificate objects from the embedded certificate in order to proceed with the request. BTW, is this the correct way to implement Client Certificate Authentication on Android app ? if no, please advice.

like image 901
Tsahi Deri Avatar asked Feb 01 '16 16:02

Tsahi Deri


People also ask

How do I address WebView SSL error handler alerts?

To correct the issue, please update your apps code to invoke SslErrorHandler. proceed() whenever the certificate presented by the server meets your expectations, and invoke SslErrorHandler. cancel() otherwise.

What is Webviewclient in Android?

If you want to deliver a web application (or just a web page) as a part of a client application, you can do it using WebView . The WebView class is an extension of Android's View class that allows you to display web pages as a part of your activity layout.

What is shouldOverrideUrlLoading?

As the name indicates, shouldOverrideUrlLoading returns whether the URL loading should be overridden. If the function returns true , the WebView will abort the load for the request passed into this function.

Which method report any HTTP error in Webviewclient?

You just have to set your WebClient with overriden method onReceivedError in your WebView. Here is the snippet from some of my old test app: WebView wv = (WebView) findViewById(R. id.


1 Answers

Solved it using KeyStore to obtain the PrivateKey and X509Certificate objects :

    private X509Certificate[] mCertificates;
    private PrivateKey mPrivateKey;

    private void loadCertificateAndPrivateKey() {
          try {
                InputStream certificateFileStream = getClass().getResourceAsStream("/assets/cert.pfx");

                KeyStore keyStore = KeyStore.getInstance("PKCS12");
                String password = "password";
                keyStore.load(certificateFileStream, password != null ? password.toCharArray() : null);

                Enumeration<String> aliases = keyStore.aliases();
                String alias = aliases.nextElement();

                Key key = keyStore.getKey(alias, password.toCharArray());
                if (key instanceof PrivateKey) {
                    mPrivateKey = (PrivateKey)key;
                    Certificate cert = keyStore.getCertificate(alias);
                    mCertificates = new X509Certificate[1];
                    mCertificates[0] = (X509Certificate)cert;
                 }

                 certificateFileStream.close();

            } catch (Exception e) {
                 Log.e(TAG, e.getMessage());
         }
    }


    private WebViewClient mWebViewClient = new WebViewClient() {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            return false;
        }

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

        @Override
        public void onReceivedClientCertRequest(WebView view, final ClientCertRequest request) {
            if (mCertificates == null || mPrivateKey == null) {
                loadCertificateAndPrivateKey();
            } 
            request.proceed(mPrivateKey, mCertificates);
        }
    };
like image 141
Tsahi Deri Avatar answered Sep 20 '22 02:09

Tsahi Deri