HTTPS with mutual authentication
Tags: webdev, tomcat, java, programming
Published: 2022-06-24 12:51:17

If you want to secure your existing Tomcat server or don’t use Spring Boot there’s quite a lack of up-to-date configuration information, especially because all existing examples were made invalid by the arrival of Tomcat 10 (yes it already happened).
![xml contents](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6eqcfg4jdu5k4ostd816.png)

So because I needed a future proof SSL configuration that is also understandable to the security beginner (also me), here’s what I come up with:

```
<Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol" scheme="https" secure="true" maxThreads="150" SSLEnabled="true" defaultSSLHostConfigName="localhost">
	<SSLHostConfig hostName="localhost" truststoreFile="server-truststore.jks" protocols="all" truststorePassword="changeit" certificateVerification="required">
		<Certificate certificateKeystoreFile="server-keys.p12" certificateKeystoreType="PKCS12" certificateKeystorePassword="changeit" certificateKeyAlias="server" type="RSA"/>
	</SSLHostConfig>
</Connector>
```

1. **SSL connection**
    So you want that browsers connecting to your web server to see the trustworthy padlock icon in the address bar, by connecting with HTTPS? This means you need HTTP over SSL, or TLS actually.
    For this the server will send the appropriate certificate to the browsers, identifying itself with it. This server certificate is stored in a keystore – named like this because it stores the keys owned by the server. The element describes the location of this keystore, its type (default JKS, can be PKCS12) plus information on what’s inside and how to open it.
    Of course the certificate sent by the server must be signed by a CA the client is trusting, otherwise you’ll get SSL with a big warning “self signed certificate” – still protecting the communication from network snooping but saying nothing about the real identity of the server.

2. **Client authentication**
    So you want that only CERTAIN browsers can connect to your web server? Not a very common requirement, quite unusual for browser connections. But you’ll need it more if you build a REST API server with HTTPS and you must restrict the access to this API.
    For this the server will need to trust the client, and the client must identify itself with a certificate. The certificates the server trusts are stored in a, guess what, truststore, which is configured in the SSLHostConfig element. You also need to force this client authentication by mandating certificateVerification.

Of course you can store all the certificates in one store and use it for both above purposes but it’s always easier to explain if theyre split according to role. Most of the time all these certificates will be x509 certificates anyway, thus also the common discussion topic of “x509 mutual authentication”. 

Two notes: 

-     if for testing reasons you decide to create your own certificates, do yourself a favor and use only Keytool and namely that one from the Java version you are using on the server. Don’t mix it with different Keytool versions or with OpenSSL.
-     for all the above to work you’ll need the APR library for Tomcat as only this one supports client authentication. See also the usage of Http11AprProtocol…

Helpful links:
https://tomcat.apache.org/tomcat-8.5-doc/config/http.html
https://tomcat.apache.org/tomcat-8.5-doc/ssl-howto.html
https://docs.spring.io/spring-security/site/docs/4.0.x/reference/html/x509.html
https://www.baeldung.com/java-https-client-certificate-authentication
https://medium.com/ing-tech-romania/a-simple-mtls-guide-for-spring-boot-microservices-c6bfc9878369