I am developing a webapp that uses client certificates to authenticate against Tomcat during web service calls with Jersey. This is working great so far, but I need a web frontend on the same context that will let me administer this application. Since the SSL configuration is "per context", the only option to have the frontend use https seems to be installing a client certificate to the accessing browser, that is listed in tomcat's truststore as well (either that or discarding the use of https altogether).
To illustrate what I really want:
1. https://url-to-webapp/ws <- Should use client certificate
2. https://url-to-webapp/web <- Should just use a server certificate
Can this be achieved somehow in the Tomcat configuration, or even in the application code?
Update
I tried the configuration suggested by EJP but now I can't connect to Tomcat regardless of my use of certificates - it seems to fail during the lookup or something. If I create a HTTP connector on 8080 though, it redirects me to 8443. This is the configuration I'm using. Any ideas?
tomcat-users.xml
<tomcat-users>
<role rolename="webservice"/>
<user username="CN=ClientCert,OU=Corp,O=Corp,L=London,S=London,C=UK" password="" roles="webservice"/>
</tomcat-users>
server.xml
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="true" sslProtocol="TLS"
keystoreFile="c:\tomcat\keys\server.jks" keystorePass="password"
truststoreFile="c:\tomcat\keys\client.jks" truststorePass="password"/>
web.xml
[...]
<security-constraint>
<display-name>ClientCertificateRequired</display-name>
<web-resource-collection>
<web-resource-name>MyWebService</web-resource-name>
<description/>
<url-pattern>/webservice/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<description/>
<role-name>webservice</role-name>
</auth-constraint>
<user-data-constraint>
<description/>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>CLIENT-CERT</auth-method>
<realm-name>tomcat-users</realm-name>
</login-config>
<security-role>
<description/>
<role-name>webservice</role-name>
</security-role>
[...]
<servlet>
<display-name>Webservice</display-name>
<servlet-name>Webservice</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
[...]
<run-as>
<role-name>webservice</role-name>
</run-as>
</servlet>
[...]
You can configure Tomcat to use client-certificate re-negotiation (as opposed to initial negotiation), so that whether-or-not to ask for a client cert depends on the URL requested.
To do this, you need to use clientAuth="false"
in the connector configuration and then <auth-method>CLIENT-CERT</auth-method>
in the webapp you want to protect with a client certificate.
Note that this uses re-negotiation and thus you may have to deal with the TLS re-negotiation bug issues. In short, there was a TLS protocol flaw published around November 2009. The immediate security fix was to disable re-negotiation (unless forcing the non-safe option) and then the implementation of RFC 5746. See phase 1 and phase 2 fixes in the Oracle Java Transport Layer Security (TLS) Renegotiation Issue Readme.
For what you're trying to do, you need re-negotiation to be enabled, and for this to be secure, you'd have to use the JRE release 1.6.0_22.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With