1

I want to be able to accept both web browser clients and (automated) service clients to a single servlet running in my application. Some of the service clients will authenticate with TLS client certificates, but some will not. I do not want web browser clients to be prompted for a certificate ever, even if the user has some installed in their browser. The decision on whether to prompt for a client certificate is dynamic and based on policy according to the client, so cannot be statically configured in web.xml.

Is there a way to dynamically trigger TLS renegotiation to request a client certificate from within a servlet? If I had access to the raw SSLSocket then I could configure it to require a client certificate and then call startHandshake() to force renegotiation. As far as I can tell, there is no portable way to get hold of the SSLSocket associated with a servlet request/response though.

My application has to run in a variety of servlet containers, so I'd prefer to avoid container-specific solutions if possible. Ideally the solution would not involve a redirect, but I will accept that if it is the only way.

Neil Madden
  • 464
  • 1
  • 5
  • 14
  • I think this is related to this - https://stackoverflow.com/questions/14875094/ssl-server-socket-want-auth-option – Dzmitry Prakapenka Jan 11 '19 at 10:09
  • Not really. That question is about setting client certificate authentication to "want", which makes it optional. I can't use this setting though, because that setting will cause a web browser to prompt the user to choose a certificate if they have one installed that matches one of the configured CAs. I never want that to happen for web browser clients. – Neil Madden Jan 11 '19 at 10:20

1 Answers1

0

You wrote in comments above:

because that setting will cause a web browser to prompt the user to choose a certificate if they have one installed that matches one of the configured CAs. I never want that to happen for web browser clients

Then I vote for this is impossible to achieve from server side. TLS takes first before any data sent through secure channel. You can't determine is it web browser or not knocking at your door not asking for client identity. From TLS point of view this is just yet another unnamed network client attempts to connect. After secure connection established, data is sent, and you can determine this is browser or not.

You may want to pipe browsers (1 way ssl) and server client (2 way ssl) through different endpoints.

Otherwise you may want to implement you own TLS protocol handshake procedure.

You may want to configure browsers not to answer to client certificate requests instead of configure server not to ask if (if it would be possible) to determine this is browser-based client. May be try to guess it through the cypher suit (list of supported crypto modes) but this is definitely not servlet level of interaction.

I am curious somebody know ho to solve you question.

  • 1
    I already mentioned in the question that you can trigger renegotiation using the startHandshake() method on the SSLSocket. So you can let an initial handshake happen without the server asking for a client certificate and then (after you have identified the client by other means) trigger renegotiation to force the client to present a certificate. In TLS 1.3 this has changed though - there is no renegotiation, only [post-handshake client authentication](https://tools.ietf.org/html/rfc8446#section-4.6.2) which Java 11 decided not to implement: https://openjdk.java.net/jeps/332 – Neil Madden Feb 11 '19 at 10:18