Ssl – Tomcat two way SSL with APR loses client certificate after a few requests

certificatessltomcat

I found that when accessing a web application that uses client certificate authentication run on Tomcat/APR (on Windows) with Firefox or Chrome, the client cert is "lost" after a short while. To the app it appears the client certificate was not sent.

Example code (JSP fragment):

User client cert data:
<%= ((java.security.cert.X509Certificate[])
request.getAttribute("javax.servlet.request.X509Certificate"))[0].
getSubjectX500Principal().toString()%>

After a few refreshes of the page (where it will show the client certificate DN) the page will fail with a NullPointerException as request.getAttribute will return null. It usually happens in less than a minute. To be more precise: when reloading about once per second, the problem occurs almost every time after 30 seconds. After that each request will fail the same way, until I restart tomcat (or restart Firefox, or just clear "Active Logins" in Firefox and re-select the certificate on a new connection). After the restart the problem always returns (and goes away for 30 seconds if I restart again).

This happens with Firefox (v39 and v40) and Chrome (v44), but not with IE v11.

It also occurs with different versions of tomcat and Java (and OS bitness).

A test case using latest versions is:

  • download and extract apache-tomcat-8.0.24-windows-x64.zip
  • in the webapps folder create a folder named cert, there create a file named ccertA.jsp that contains the above code snippet
  • in server.xml add a line:

    <Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol"
    secure="true" scheme="https" maxThreads="150" URIEncoding="UTF-8"
    SSLVerifyClient="optional" SSLProtocol="TLSv1+TLSv1.1+TLSv1.2"
    SSLPassword="testing" SSLEnabled="true"
    SSLCertificateKeyFile="C:/your_server_key_private.pem"
    SSLCertificateFile="C:/ your_server_key _public.pem"
    SSLCACertificateFile="C:/supported_client_CAs.pem" />

  • start tomcat by executing startup.bat

  • open the page https://localhost:8443/cert/ccertA.jsp and keep refreshing it every few seconds

(see the bug linked below for a complete testcase with all the needed files, including certificate files)

If I don't use APR (by deleting the tcnative-1.dll file and adapting the connector syntax for JSSE) the problem does not happen.

Tried versions, all having the issue:

  • apache-tomcat-8.0.24-windows-x64 (also 32 bit version)
  • apache-tomcat-6.0.44-windows-x64
  • Java 1.6.0 Updates 12 and 45
  • Java 1.8 Update 51
  • Windows 7 Pro SP1 64 bit
  • Windows 7 Pro SP1 32 bit
  • Windows 8.1 Pro 64 bit
  • Windows 10 Home 64 bit
  • Firefox versions 39.0 39.0.3 and 44
  • Chrome v44
  • Ubuntu 14.04 LTS 64 bit / tomcat 7.0.52-1ubuntu0.3 / libapr1:amd64 1.5.0-1 / libtcnative-1:amd64 1.1.29-1

A similar issue was discussed on the tomcat-users mailing list in 2010: Client certificate gone after 1 minute timeout (SSL, APR) but with no solution. I posted there myself recently ( Firefox SSL with APR – losing client certificate has a bit more details), but it is basically just my monologue.

Edit: Certificate info

Originally I tested with a server certificate issued by my private testing CA. Now I also tried with a "real" certificate issued by trusted CA. (I used my personal certificate. The browser complained about the hostname mitmatch which I clicked away).

Edit: bug report

Reported as Bug 58244 – two way SSL loses client certificate after a few requests

Suggestions on how to debug the issue are welcome.

Best Answer

I had too many issues with using client certificates with java apps (on client side as well as on a server). APR helps but it has issues of its own. Eventually, I decided to stop trying and now I offload SSL processing to a proxy in front of the app. Both Apache and Nginx work well in this role.