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?
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.
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[]))