EddyYosso
EddyYosso

Reputation: 156

Configuring HTTPS certificate usage based on url in Tomcat

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

Upvotes: 5

Views: 4280

Answers (2)

Bruno
Bruno

Reputation: 122649

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.

Upvotes: 4

user207421
user207421

Reputation: 310913

Just define the first URL as secured and requiring both confidentiality and a specific role, and define the web app as using SSL client authentication. Define the second URL as not requiring a role. This is all in web.XML. Then define yourself an appropriate Realm to check identities against and get roles from.

Upvotes: 2

Related Questions