Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring security x.509 authentication - accept certificates based on their issuer Certificate Authority

I am using Spring Security to authenticate using an x.509 certificate, and it works only when the client certificate which is configured in the browser key-store is present in server trust-store.

How it is working currently:

  • I have configured the SSL client authentication as optional (server.ssl.client-auth=want , like in this post)
  • I have configured a server trust-store that contains all client certificates. If the certificate presented by the client is in the trust-store, the mutual SSL connection is created.
  • When I have the client certificate(s) present in the server-side trust-store, Firefox opens a popup with my client-side certificate(s), which I can choose and the mutual SSL connection is established.
  • I have configured Spring Security to extract the username from the SubjectDN of the client certificate and check it against a UserDetailsService. If a UserDetails object is returned for that username, the authentication process completes successfully

The problem is that if I remove the client-certificate from the server-side trust-store, Firefox doesn't open this popup anymore, and only a one-way SSL connection is made. Even if the Root CA cert is present in the server trust-store.

What I want:

  • store in the server trust-store only the certificate of a Root Certificate Authority
  • allow mutual SSL connection when the client presents a certificate issued by the Root CA in the server trust-store (even if the client certificate isn't present in the server trust-store)

I am also intrigued by two resources on the internet. In this tutorial on Baeldung, it says that all client certificates must be stored in the server trust-store for X.509 auth to work (which confirms my experience).

You must remember that for each user that should be verified by the server, its own certificate needs to be installed in the configured truststore. For small applications with only a few clients, this may perhaps be practicable, with an increasing number of clients it may lead to complex key-management for users.

However, this tutorial by @robinhowlett says that

The client will present its certificate in its keystore to the server, and the server will validate the client certificate’s chain using the CA certificate in the server’s truststore.

This is basically what I want to achieve, but am not able to.

Bottom line: did someone manage to store one or more Root CA certificates in the server trust-store and use client certificates issued by these Root CAs to authenticate via X.509 mutual SSL handshake in Spring Security?

I am using Spring Boot 1.5.2.RELEASE (spring-security-web 4.2.2.RELEASE). I have tested my working SSL authentication with Firefox 53.

like image 309
Andrei Epure is hiring Avatar asked May 03 '17 17:05

Andrei Epure is hiring


1 Answers

I found my problem - I was modifying the trust-store (removing the client cert and leaving only the CA cert) while the server was up (Tomcat, in my case). But the trust-store is kept in memory and gets read only once, when the JVM is initialized (details on this ServerFault post). So trust-store changes are not being read during runtime by Tomcat.

So the answer is simple: yes, if only CA certs are present in the trust-store, during the SSL handshake the server communicates to the browser it wants client certificates issued by the trusted CAs and then the browser prompts the user to select a certificate that is issued by a trusted CA (if such a cert is present in the browser keystore).

However, if a CA is added dynamically to the server trust-store while the server is up and running, it won't be detected. The new CA will only be recognized after the server reboots (and the JVM is re-initialized).

like image 100
Andrei Epure is hiring Avatar answered Oct 17 '22 07:10

Andrei Epure is hiring