PeteLinforth, Public Domain (https://pixabay.com/en/background-vault-render-3d-steel-1242666/)

Taming the Two way SSL Authentication

Nidhi Sadanand
Walmart Global Tech Blog
3 min readDec 14, 2016

--

In Walmart’s SOA based architecture, service to service interaction using one way SSL, where the client validates that the server is secure, is fairly common and is the norm in RESTful communication. In cases where there is PCI or HIPAA data involved, there is two way SSL authentication where the server now validates if the client is known. This is much less common and setting it up the first time can be quite challenging. Much of the information I have provided below is available on the Internet, but it takes a while to piece it together. Therefore, I am providing a gist of this and what needs to be done if you use a Java Spring and JaxRS (Apache framework for REST based services) setup.

A Quick Primer on the Two Way SSL Handshake

  1. Initial Connection Establishment
  2. Next is the negotiation of the Cipher Suites with the client providing a list of supported Cipher suites for the server to pick.
  3. Server picks a Cipher suite and sends Server Certificate with public key and in two way SSL, it requests for a certificate signed by any of a list of CA’s it trusts.
  4. Client validates the Server Certificate against its Trust Store and sends its own certificate which has been signed by one of the trusted authorities.
  5. Server validates the certificate and acknowledges.
  6. Client sends a secret session key for further symmetric encryption of data.

Setting up the Trust Store and Key Store

  1. Ensure that you have the client certificate with the private key. There are various file formats and ways to convert between them — but Java understands JKS & PKCS12. This private key store configuration is required for two way SSL auth. One way SSL auth will just look at your trust store.
  2. Ensure that the server’s certificate or its intermediate or Root CA is added to your TrustStore. TrustStore is the repository of all the certificates to the servers you connect to and trust.
  3. Once the above is done, it is ready to be integrated to your application
    To wire it up if you are using Spring and Apache-JaxRS add the following dependencies in your pom.xml and the conduit configuration to your Spring beans configuration . The key to this is using an JaxRS HTTP conduit — which is essentially defines the socket connection.

Tip: You could check if your browser SSL connection works by importing your client cert into your browser using the browsers Advanced Settings. On entering the secure server URL, if the handshake is successful, you will get a valid HTTP success or error code. If, however, there is something wrong with your client certificate, the SSL handshake that the browser issues will fail and you will get a browser error.

Maven Dependencies

<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-common-schemas</artifactId>
<version>2.3.11</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId> <version>2.7.7</version>
</dependency>

Spring Configuration for JaxRS Connection

//Bean initialization
//Schema Declaration
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:http="http://cxf.apache.org/transports/http/configuration"
xmlns:sec="http://cxf.apache.org/configuration/security"
xsi:schemaLocation="http://cxf.apache.org/configuration/security http://cxf.apache.org/schemas/configuration/security.xsd">
//Conduit wiring
<http:conduit name="${serviceURL}.*">
<http:tlsClientParameters secureSocketProtocol="TLS" ><sec:certAlias>myalias</sec:certAlias>
<sec:keyManagers keyPassword="password" >
<sec:keyStore type="JKS" password="Keystore_password" file="${file_path_to_keystore}"/>
</sec:keyManagers>
<sec:trustManagers>
<sec:keyStore type="JKS" password="trust_store_password" file="${file_path_truststore}"/>
</sec:trustManagers>
<sec:cipherSuitesFilter>
<sec:exclude>.*_EXPORT_.*</sec:exclude>
<sec:exclude>.*_EXPORT1024_.*</sec:exclude>
<sec:include>.*_WITH_DES_.*</sec:include>
<sec:include>.*_WITH_AES_.*</sec:include><sec:exclude>.*_WITH_NULL_.*</sec:exclude>
<sec:exclude>.*_DH_anon_.*</sec:exclude>

</sec:cipherSuitesFilter>
</http:tlsClientParameters>
<http:client AutoRedirect="true" Connection="Keep-Alive" CacheControl="no-cache"/>
</http:conduit>

Things to Note

  1. The JaxRS creates a conduit for every connection and it does not look at the javax.net.ssl.keyStore property by default, if you have specified it as a system property.
  2. If your conduit configuration is not picked up from the classpath you can pass the location as a file path configuration parameter when you create the Web Client using JaxRS.
  3. Make sure the alias entry is correct and as specified in the KeyStore.
  4. Export Ciphers are vulnerable to SSL freak attacks and should be excluded.
  5. There are weak implementations of AES & DES hence it would be good to run a review using this website.
  6. Usage of strong passwords and password encryption services is recommended.

Hopefully this post helps you save time if you are trying to wire up two way SSL communication!

--

--