Intro

I use Bitwarden as my password manager, more specifically, I use vaultwarden, which is a rustified self-hosted version, it's completely compatible with the official Bitwarden clients while being significantly lighter and easier to run. I've been using it for a good number of years now and it's been great, but MTLS support has always been missing from the Android app.

There had been an issue open for it since 2019, and I'd been following it along for a long time, hoping an implementation was on the way. Finally, that day has come.

Why MTLS?

I use Cloudflare Tunnels to access all of my self-hosted services, including vaultwarden. In most cases, this is great as I've got Github SSO configured for most apps and I can use it to authenticate to my services. For some apps though, this isn't possible, as they error out when receiving an unexpected response from Cloudflare instead of the backend service itself. This is mostly the case with mobile apps, which expect a direct connection to the backend service. In these cases, I use MTLS to authenticate the client to the server, allowing access to the origin without directly exposing it to the internet.

Two good examples of this are Immich and Homeassistant, both of which don't play nicely with Cloudflare Tunnels, but support MTLS (and even custom header authentication!) to authenticate the client to the server. I've had this set up for a while now, but the Bitwarden Android app has been a specific pain point in that I've had to leave it exposed to the internet with restrictive rules based on GeoIP and User Agent. This is far from ideal, an attacker could simply use a VPN to bypass the GeoIP restrictions, and spoofing a User Agent is trivial. MTLS would allow me to secure the connection to Bitwarden without exposing it to the internet, as the app would need to present a valid client certificate to Cloudflare before it can even establish a connection to the origin.

To add to this, the place I work at runs SSL decryption on the web-browsing firewalls, which 'theoretically' poses a privacy risk, as some major security vulnerability on the firewall (and these are Palos, so it's not out of the question) could allow an attacker to intercept decrypted traffic and access sensitive information. While I trust my team, I certainly don't trust Palo with their later releases. With MTLS, the firewalls are unable to decrypt the traffic as the client certificate is required to establish a connection, so the traffic remains encrypted end-to-end. Considering I use the Bitwarden browser extension on my work laptop, this is an absolute must-have - and it's something I would have implemented sooner if not for the Bitwarden Android app not supporting it.

Support

As of February 10th, 2025, the Bitwarden Android app now fully supports MTLS. I've now enabled MTLS for the vaultwarden subdomain in Cloudflare, and the app is able to connect without any issues. I'll need to set this up for the browser extension as well, but that is extremely simple and something I've done before. This means I can finally remove my useragent rule, which I was only reliant on for vaultwarden.

Internal access to my vaultwarden instance connects via an internal load balancer, and as this is not internet-facing, I do not request a client certificate for it. This means the only places I should need to set up MTLS are my work laptop and my personal phone, and while on my internal network they should continue to work as they did before. This is a great improvement to my security posture, and I'm very happy to see Bitwarden finally supporting MTLS after so long.