Skip to content Skip to sidebar Skip to footer

Android App Client Mutual Tls With Java Server

I'm trying to send https requests to my server using mutual TLS. The server I got working successfully with TLS. But I can't figure out how to do this on the client-side (Android a

Solution 1:

What you are looking for is mutual authentication based on certificates. Both the server and the client needs to trust each other to communicate. And if the server just trust that specific client only it shouldn't be possible for any other client to do a request.

The above example looks okay, but it will be easier to configure with the example below:

importstatic java.util.Objects.isNull;
importstatic org.apache.commons.lang3.StringUtils.isBlank;

import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;

publicclassSSLTrustManagerHelper {

    private String keyStore;
    private String keyStorePassword;
    private String trustStore;
    private String trustStorePassword;

    publicSSLTrustManagerHelper(String keyStore,
                                 String keyStore,
                                 String keyStorePassword,
                                 String trustStore,
                                 String trustStorePassword) {
        if (isBlank(keyStore) || isBlank(keyStorePassword) || isBlank(trustStore) || isBlank(trustStorePassword)) {
            thrownewClientException("TrustStore or KeyStore details are empty, which are required to be present when SSL is enabled");
        }

        this.keyStore = keyStore;
        this.keyStorePassword = keyStorePassword;
        this.trustStore = trustStore;
        this.trustStorePassword = trustStorePassword;
    }

    public SSLContext clientSSLContext() {
        try {
            TrustManagerFactorytrustManagerFactory= getTrustManagerFactory(trustStore, trustStorePassword);
            KeyManagerFactorykeyManagerFactory= getKeyManagerFactory(keyStore, keyStorePassword);

            return getSSLContext(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers());
        } catch (UnrecoverableKeyException | NoSuchAlgorithmException | CertificateException | KeyStoreException | IOException | KeyManagementException e) {
            thrownewClientException(e);
        }
    }

    privatestatic SSLContext getSSLContext(KeyManager[] keyManagers, TrustManager[] trustManagers)throws NoSuchAlgorithmException, KeyManagementException {
        SSLContextsslContext= SSLContext.getInstance("TLSv1.2");
        sslContext.init(keyManagers, trustManagers, null);
        return sslContext;
    }

    privatestatic KeyManagerFactory getKeyManagerFactory(String keystorePath, String keystorePassword)throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException, UnrecoverableKeyException {
        KeyStorekeyStore= loadKeyStore(keystorePath, keystorePassword);
        KeyManagerFactorykeyManagerFactory= KeyManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, keystorePassword.toCharArray());
        return keyManagerFactory;
    }

    privatestatic TrustManagerFactory getTrustManagerFactory(String truststorePath, String truststorePassword)throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
        KeyStoretrustStore= loadKeyStore(truststorePath, truststorePassword);
        TrustManagerFactorytrustManagerFactory= TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(trustStore);
        return trustManagerFactory;
    }

    privatestatic KeyStore loadKeyStore(String keystorePath, String keystorePassword)throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
        try(InputStreamkeystoreInputStream= SSLTrustManagerHelper.class.getClassLoader().getResourceAsStream(keystorePath)) {
            if (isNull(keystoreInputStream)) {
                thrownewClientException(String.format("Could not find the keystore file with the given location %s", keystorePath));
            }

            KeyStorekeystore= KeyStore.getInstance(KeyStore.getDefaultType());
            keystore.load(keystoreInputStream, keystorePassword.toCharArray());
            return keystore;
        }
    }

}

Here you need to provide the location of the keystore and truststore, and also the passwords. The public class will provide you the ssl context which you can load into your http client.

Make sure you have a client keystore with private and public key, and a truststore where you have the public key of the server. And make sure that the server has the public key of the client in its truststore. You also need to provide your server an additional properties in the application.yml file which enforces the server to validate the client. The property is: client-auth: need

See here a full example of setting up mutual authentication for server and client including example project spring-boot-mutual-tls-sll

Post a Comment for "Android App Client Mutual Tls With Java Server"