0

I know that Tomcat provides both SNI and mutual authentication, but is it possible to enable MA only for selected applications/paths? I.e. let's say that I have the following applications/endpoints on my server:

/app1
/app2/human
/app2/robot

where /app2/human is used by humans and /app2/robot is used by robots, computers and other devices (so for example /app2/human serves HTML and /app2/robot serves JSON). Now, can I somehow configure Tomcat to accept connections to /app1 and /app2/human via SSL without MA and to /app2/robot only if client presented valid certificate?

Of course I want to do it without configuring separate ports/connectors for each application, this is easy.

Thanks in advance.

Jędrzej Dudkiewicz
  • 1,053
  • 8
  • 21

2 Answers2

1

According to this and by reading the docs, you cannot have selective mutual auth on a per-path basis. It is all or nothing because client auth is configured at connector level. You are probably looking for SSL renegotation with client auth which is probably not implemented as you might be used to from Apache HTTPd.

Community
  • 1
  • 1
Michael-O
  • 18,123
  • 6
  • 55
  • 121
  • Thanks, that's what I thought looking at classes like SSLSocket, SSLSocketFactory and so on. It seems that it can be done by hand as it was written in the post you linked - set "wantClientAuth(true)" instead of "needClientAuth" and perform "manual" verification - in fact it seems that it is enough to check "((SSLSocket)socket).getSession().getPeerCertificates()" - if client isn't authenticated, it will throw an exception javax.net.ssl.SSLPeerUnverifiedException which is enough to drop connection or return something meaningful. – Jędrzej Dudkiewicz Jul 15 '16 at 14:16
1

Tomcat doesn't provide selective-mutual-authentication for different paths, but if you only need to have such selective-mutual-authentication apply at the webapp-level (and not inside of a particular web application), you might be able to get away with having a separate <Connector> for a special web application. This requires a separate <Service> and therefore <Host>, and of course a different port number (unless you happen to have a separate network interface you can use to preserve ports).

I haven't tried it, but I would imagine that, theoretically, SNI+client-auth could be configured so that a particular hostname would have different client-authentication requirements, but there is no such code in Tomcat to support that currently.

Tomcat can be configured to use a different trust store and a different certificateVerification setting per hostname, but it doesn't allow you to change it per path.

Another option would be to configure Tomcat to "want" (or even require) a client cert, and then perform the checking yourself using a Filter. Filters can be applied on a per-path basis, plus your application becomes more portable because you aren't relying on some feature that may be Tomcat-specific.

Have a look at this thread for how I did this a few years ago. There is (eventually) some sample code plus lots of references for how I got all the information to put it together: http://markmail.org/thread/vxwwli5nzt4itfr2

Christopher Schultz
  • 20,221
  • 9
  • 60
  • 77
  • I think the second connector is terrible overhead for a quite simple thing. With all the nice stuff Mark Thomas has added with TLS virtual hosting in Tomcat 9, this is a really missing feature for those in need. – Michael-O Jul 15 '16 at 17:26
  • 1
    I guess only the guy who makes the commit gets any love :( – Christopher Schultz Jul 15 '16 at 19:18