Ending TLS Client Authentication Certificate Support in 2026

60 pabs3 43 5/18/2025, 1:59:43 AM letsencrypt.org ↗

Comments (43)

bjornsing · 22h ago
Why are client certs not more popular? They seem like a pretty clean abstraction compared to all the API keys and JWT tokens floating around.
jeroenhd · 22h ago
They're used in a whole bunch of industries, but not in the sexy ones.

Renewal is the most important issue. Certificate stores often suck and for tokens there are various existing protocols for re-issuing expiring ones. For certificates, you're stuck doing your own thing.

For local applications, UI/UX of the system supposedly in charge of certs is often absolutely terrible. I've had the displeasure of working with Java key stores and I'd rather rewrite the auth mechanism than deal with that bullshit again.

The use case they would perform excellently in (centrally managed corporate networks) are also the places where you will find terrible middleboxes that will kill any protocol they don't understand.

TLS client certificates could've been what passkeys are today, and they could've been what OAuth2 tokens have become, but the terrible development experience killed them off before they could bloom. I mostly blame web browsers, who didn't bother improving their UI for certificates after the day they first implemented them. Hacking OAuth2 on top of HTTPS calls is pretty easy compared to figuring out how to refresh a user certificate.

pixl97 · 21h ago
Java keystores for user clients are just a nightmare. So much if my time is used up helping customers that don't understand how they work.
thayne · 19h ago
It's a nightmare for using a custom CA for server certs too.

You can't just add a new CA, you have to rebuild the entire keystore. And then you need to do it again every time you update the JVM, or risk missing updates to the default keystore.

For some reason the keystore is required to be protected by a password, even if it doesn't contain any secret keys.

The documentation for the tools that manage keystores is incomplete and sometimes out of date.

The whole thing is a relic from another time and could really use some modernization.

jeroenhd · 12h ago
There are workarounds for that, by specifying a custom key store file and overriding the socket factory to force it to load your keys.

Unfortunately, most example code for SSL socket factories just disable TLS validation entirely. So yes, your custom CA now works reliably, but unfortunately so do self-signed certificates if you're not careful.

Luckily, modern Java doesn't need keystores anymore. Unfortunately, half the world seems stuck on Java 8.

pixl97 · 11h ago
>most example code for SSL socket factories just disable TLS validation entirely.

I see this happen in large enterprise far more often than it should, like the kind of business where disabling SSL is a baaaad idea for the kind of attacks they're apt to get.

aragilar · 20h ago
The other challenge is proxies. When the backend that cares about client cert is behind a proxy you need to dig into the less-familiar parts of the proxy and try to work out either how to pass the certificate on or extract the information from it.
jeroenhd · 12h ago
The typical solution for reverse proxies is to extract the relevant information and pass it on as either custom headers or environment variables. That works fine, assuming you make sure to ignore the headers the client might send to take that information, of course.

It's pretty easy to set up in Apache and Nginx at least.

For forward proxies, the only option is to either accept the connection unaltered or to drop the connection entirely.

benced · 21h ago
Java KeyStore is so awful, I cannot believe it became a thing. It single-handedly disqualified Spinnaker (the Netflix K8s deployment thing) for me.
ojhughes · 13h ago
netty-tcnative can remove the need for a Java keystore in Netty based applications https://netty.io/wiki/forked-tomcat-native.html
devman0 · 19h ago
Client certs are strongly bound to the TLS handshake, and thus a connection, which makes them pretty unfriendly to a lot of proxy driven architectures, where as JWTs and Cookies can pass through proxies trivially, and are bound to requests not connections. There is some work being done around standardizing pass through of client cert information through proxies, but I'm not aware of any widespread support.
cyberpunk · 16h ago
Istio passes the real client cert in a header through to the backend which makes it not too bad to validate in such cases (nginx or whatever can quite easily do this too)
devman0 · 5h ago
Header passthrough is nice to have, but there isn't really a standard for it for TLS, and it isn't well supported by most applications that are interested in doing mTLS. Additionally there is a trust component required between proxy and application and while can be accounted for in the architecture between the two a JWT instead passes through nicely and can be independently validated by the application.
tptacek · 20h ago
There are a lot of reasons, but Colm MacCárthaigh has some particularly interesting ones:

https://news.ycombinator.com/item?id=25380301

nmadden · 19h ago
Adding some OAuth helps a bit: https://neilmadden.blog/2022/01/20/why-the-oauth-mtls-spec-i...

(I quite like the combo of app-level OAuth plus mTLS service mesh for backend comms).

edelbitter · 22h ago
A really clean abstraction, but not any more once you try to correctly use it over traditional SSL toolkit APIs (e.g. CVE-2025-23419) or in conjunction with any of the the more interesting web scenarios (HTTP/3, rel="preconnect", CORS, CDNs..)
SoftTalker · 22h ago
Users can’t manage them and nobody has come up with software that can.

I have worked with PhDs who can’t even manage ssh keys.

nirui · 21h ago
> PhDs who can’t even

Not a good point.

I've experienced PhDs who can't (even, some may add) write shell script. Maybe they just hate the syntax, or specifically the $ symbol, maybe both. But, they did do fine job otherwise and has successfully replaced me, a person who can write a bit shell script :(

SoftTalker · 6h ago
The point is that even very smart people in technical fields can just be bad at/not care/willfully refuse to use stuff like this. It's a non-starter for a general-purpose authentication mechanism if the user has to understand concepts such as "private" and "publc" keys.

Even 2FA solutions like Google Authenticator are simple enough that you just need to scan a QR code but very few people use them and even fewer actually bother to print/save the backup emergency codes for use if they lose access to their auth device.

People can (sometimes) handle passwords, and an emailed reset link if they forget.

notpushkin · 22h ago
Tooling problem, as always.
thayne · 21h ago
If only there was a standard protocol for trading credentials and a CSR or equivalent for a signed certificate. Kind of like ACME for client certs that uses login credentials instead of dns. And maybe then browser support for logging in using that to create a client cert instead of setting a cookie.
et1337 · 21h ago
In case anyone misses the joke, I think this is what passkeys are.
lhamil64 · 21h ago
I've wondered this too. I have a little home server with some self hosted services, and I use a client cert on the reverse proxy to add an extra layer of security before the user can even reach the app. This works fine when accessing things via the browser, but if you want to use something like a mobile app, it almost certainly won't have support for it. It's up to every single app dev to implement support for passing in a client cert on the http requests.

I suppose a VPN is really the better answer here, but that's a pain if I want to give anyone else access and is less granular.

No comments yet

pabs3 · 20h ago
The browser UI for them has always been bad, and has gotten worse over time.
kmeisthax · 22h ago
Because if you use a token, you don't have to pay for a certificate.

TLS PKI is designed to do one thing and one thing only: bind a keypair to a domain name. This is great for authenticating servers and terrible for authenticating clients. The question that a server wants to ask of a client is not "is this server authorized to serve this domain name", it's "is this a key I authorized to access this resource". The latter question is not just "inappropriate for the TLS PKI", it's inappropriate for any public PKI[0]. The only appropriate PKI for client authentication is for each server to run its own private client PKI.

If you insist on using client certs that are signed by the TLS PKI, then everyone who wants to connect to your API needs to buy a cert from a third-party that will provide no additional security for you or them, compared to the moral equivalent of ~/.ssh/authorized_hosts. If you have a particularly complicated server setup, then rolling your own client root would at least give you centralized issuance and revocation control.

Ok, let's say you set up your API to use client certs. You've just massively complicated the most common use case for your API: pinging it from a web browser running your JavaScript. There is no API in the web standard for a random website to enroll a client cert in your browser, and you can't specify a client cert in HTTP fetch or anything. Client certs are instead managed with the same terrible UX as the root cert store, which is deliberately obfuscated for fairly obvious "keeping the user from hurting themselves" reasons. So now you have to give your users a cert file and guide them through a bunch of nonsense to install the cert.

Furthermore, if any other website does this, now all your users have to pick which identity they want to use whenever they go to a website that wants client certs. They aren't bound to specific domain names like, say, password manager items can be. The only way you could avoid this... is by using a public client cert PKI, which means now all your users need to pay $$$ to a third party just to login to your website, which is a terrible idea.

Tokens, passwords, and passkeys avoid all of this nonsense and give you exactly what you want: client authentication, nothing more or less. TLS client certs are the sort of thing an engineer cooks up because it sounds nice and symmetrical. Oh, servers have certs, why can't clients have certs? But in practice certs solve the wrong problem and carry too much baggage for clients.

[0] Public public key infrastructure

jeroenhd · 21h ago
Nobody is making you buy certificates to authenticate to an API. You'd get a certificate file the same way you'd get an API key, from whatever portal you're gaining access from. Nobody is trusting random PKI certificates to access APIs.

You also don't need any special certificates. The authentication certificates you hand out to API clients can be self-signed if that's what you want, but you probably want an internal CA of some kind to hand out/revoke certificates the same way you have some kind of API key storage.

You're right that the browser UI is pretty terrible. Especially on Firefox, I should add, which decides to maintain its own key store. On all other platforms you just open the certificate and hit next a few times and you should be good.

As for picking the identity to use, there are easy ways in the TLS protocol to signal what certificates qualify, and there's no way you're going to have multiple certificates signed by the same Acme Corp Ltd. with private key 0xffaabb... Websites that aren't set up correctly will prompt users for a certificate to use, but that's the other websites' fault, as well as the browser's to be honest.

Client certificates work fine. They work so well, that they've been reinvented and stuffed into JWT, but now in weird JSON. Various Kubernetes overlay systems use auto-provisioned client certificates to ensure confidentiality and authentication between pods (the cloud world calls it mTLS though).

tptacek · 20h ago
JWT authenticates requests, not channels.
thayne · 20h ago
Client certs have a few advantages over API keys.

First of all, it gives the server more certainly that the other side of the TLS connection is the authenticated user, and not a MitM[1].

Secondly, if the message is intercepted, the secret key isn't compromised, and the secret key can be kept more secure than an API key that has to be sent with every request.

It also allows the signing party to be different from the verifying party. To be fair JWTs using asymmetric crypto also have this property.

And client certs, often using a private CA, are frequently used for server-to-server communication.

You are right about browsers not having good support for client certs, but there isn't any fundamental reason that couldn't be better.

As far as public key infrastructure, I agree that for client certs it isn't quite as useful as it is for server certs, but there are situations where it could be useful. Suppose a server for example.org makes a request to example.com. With a client cert signed using PKI, example.com can know that the request actually came from example.org, without having any previous establishment of a trust relationship between the two parties. That is a relatively niche use case, but I could see it being useful in federated protocols.

[1]: or at least if it is a MitM, it has access to the private key for the cert.

7bit · 16h ago
> First of all, it gives the server more certainly that the other side of the TLS connection is the authenticated user, and not a MitM[1].

The certificate (or rather the privkey) is -- like the token -- a secret that only the client and the server should know.

Certificate-based authentication and token do protect equally from MITM. And MITM attacks are equally possible when cert or token auth is being done.

The only thing where cert based auth got the client shines is that you don't have to move a new token over the wire, initially.

thayne · 6h ago
Consider if a malicious actor is able to fool the client into using http instead of https, or is able to sign arbitrary certs, because they control a CA that is trusted by the client (as in some corporate firewalls for example, or malware installed a bad CA). Now the client sends the auth token as part of the request, the MitM can intercept it, and get the auth token, and the server has no way of knowing there is a third party involved.

But with a client cert, intercepting the request gets you nothing. You don't have the secret key, so there isn't any way for you to complete the TLD handshake with the server.

> The certificate (or rather the privkey) is -- like the token -- a secret that only the client and the server should know.

No, the server doesn't need to know the privkey at all, it only needs to know the public key of the CA that signed the cert.

dingaling · 20h ago
> Why are client certs not more popular?

They needed a cool name. I present: Passkeys

silon42 · 14h ago
Seems inferior and proprietary smelling.
CaliforniaKarl · 22h ago
> This change is prompted by changes to Google Chrome’s root program requirements, which impose a June 2026 deadline to split TLS Client and Server Authentication into separate PKIs.
greatgib · 14h ago
Wtf, so now you will not be able to use the same cert for bidirectional TLS connection.

And this is totally a free user hostile change with dubious justification.

Each service that will accept the client cert can decide or not to accept a root certificate. And chrome is not even on the server side, so I don't understand why they have a say in what should be acceptable by a server (except the monopoly they have on the client to be able to refuse certs with this flag).

So now you will have to pay again legacy cert authorities to be able to use TLS client cert. Just to be put in perspective with the recent changes pushed by the same actors to enforce a reduction in validity duration of certificates to short periods, like less than a year when you need to constantly go back to your official root cert authority.

All of that without a valid widespread problem that they would be trying to fix.

In addition, letsencrypt could continue to support a dedicated profile for that but they won't. Discontinuing something they even already created to fix the issue. So TLS client cert will become a "pro" limited feature...

aaomidi · 13h ago
It really doesn’t make sense to have the client cert be issued by a publicly trusted CA.

What’s the assertion being made with that client cert?

egberts1 · 22h ago
Aaaaaw shoot.

There goes my private WireGuard client-side TLS certificate for tunneled SSH.

Just need to bashify all the certificate creation ... again.

JCattheATM · 6h ago
Why are you tunneling SSH over WireGuard?
throwaway81523 · 22h ago
CA.pl has 9 lives.
arccy · 17h ago
mkcert is pretty painless
flowerthoughts · 18h ago
> This change is prompted by changes to Google Chrome’s root program requirements, which impose a June 2026 deadline to split TLS Client and Server Authentication into separate PKIs. Many uses of client authentication are better served by a private certificate authority, and so Let’s Encrypt is discontinuing support for TLS Client Authentication ahead of this deadline.

Makes sense, even if inconvenient. Client auth is something LE can't provide as much validation of, compared to server certs.

Based on this: https://googlechrome.github.io/chromerootprogram/#322-pki-hi...

> To align all PKI hierarchies included in the Chrome Root Store on the principle of serving only TLS server authentication use cases, the Chrome Root Program will "phase-out" multi-purpose roots from the Chrome Root Store.

Rationale lacking.

ChrisArchitect · 22h ago
GauntletWizard · 22h ago
I strongly disagree with this change. You should probably never accept client certificates signed by Let's Encrypt, but I think that it normalized something very healthy in the ecosystem: issuing one certificate that acted as both server and client certificate. I have spent surprisingly little time on making this work in the TLS ecosystems of my clients, automatically building per-service TLS certificates - allowing a robust internal infrastructure of whitelisting client services while being simple enough for devs to implement themselves.

What I really wanted to do, and have proof of concept'd with only slightly more time, is per pod certificates, identifying a service account. It looks like this is progressing in mainline - https://github.com/kubernetes/enhancements/issues/4317 - albeit very slowly.

ymyms · 22h ago
I am also bummed out by this change. I really like the idea of using a certificate as a single identity for a service. Things could connect to a service using normal TLS but the service could also authenticate itself to other services using mTLS.

After this change I'd need a separate certificate for the service to use for mTLS.