Search code examples
securitytomcattls1.2access-controlclient-certificates

Passing the DN of client's certificate to the deployed app in Tomcat


I configured Tomcat to require mutual authentication over TLS by setting clientAuth="true" in conf/server.xml file:

<Connector 
      port="8443"
      protocol="org.apache.coyote.http11.Http11NioProtocol"
      maxThreads="150"
      SSLEnabled="true"
      scheme="https"
      secure="true"
      keystoreFile="conf/server.p12"
      keystorePass="1t3TcUQY*2j^"
      truststoreFile="conf/cacerts"
      truststorePass="fx!eAKQO2^0c"
      clientAuth="true"
      sslProtocol="TLS"
      sslEnabledProtocols="TLSv1.2">
</Connector>

Everything is good, and Tomcat only accepts clients with valid certificates.

The problem is that the web app deployed in Tomcat has no idea of the identity of the client. By identity, I mean the subject info, such as its distinguished name (DN), that appears in the client's certificate. Therefore, the web app cannot make access control decisions based on the identity of the client.

Is there a way for Tomcat to pass this information to the deployed we app upon successful authentication?


Solution

    1. Client certificates are accessible as request.getAttribute("javax.servlet.request.X509Certificate") as an array of certificates. Read the Servlet Specification for the official reference. In Servlet 4.0 specification that is Chapter 3.10 SSL Attributes.

    2. If your application is configured with login-config/auth-method of CLIENT-CERT then an Authenticator in Tomcat will perform authentication of client certificate. The actual processing is delegated to a Realm.

      If the authentication is successful, a user name is extracted from the certificate and a java.security.Principal is created. Extraction of the user name is configurable with attribute X509UsernameRetrieverClassName of the Realm. See Realm configuration reference.

      (For reference, in Tomcat 9: org.apache.catalina.authenticator.SSLAuthenticator.doAuthenticate(), org.apache.catalina.realm.RealmBase.authenticate(X509Certificate[]))