In defense of client certificates
blog.bimajority.org
blog.bimajority.org
Things started to go sideways when web developers wanted to exercise control over login form presentation, which just makes it very hard to prevent scripts to tamper with them, and the heavyweights that control web browser development simply has had no interest.
I'd like to see the above implemented, it's also time to get SRP in there, and an opportunity for servers to serve pre-filled CSRs, just like the article describes. I just don't know how to get there. Perhaps the bigger institutions such as CERN (they certainly have the respect required) can take a more active part in web browser development.
In the mean time, we still have Kerberos (and HTTP Negotiate). It works well for always online internal applications, and you don't have to mess about with revocations.
There's also this implementation of Kerberos in client-side JavaScript:
https://github.com/davidben/webathena
HTTP Negotiate is also super messy in similar ways (For instance, I'm not sure how to authenticate using IE if your current Windows account is a local account instead of a domain one). It definitely works, but not well.
If you've got a TRUSTED certificate authority (your definition of "trust" may vary) and secure key storage (PKCS#11 smartcard, etc.) then certificate-based authentication gives you a tremendous amount of authentication security.
But also -- why does it make sense that any website on the public internet can potentially find your US-government-signed identity? That's not even a thing the government wants. You can just do logins against a single government-run service and limit authentication to that one origin, and have it produce signed, encrypted statements that you can pass to other authorized servers. And then you also get auditing, revocation, etc. through that single service.
It seems to me like you necessarily want a custom solution and custom software here; I'm not understanding how the removal of client-cert support from public builds of Chrome or Firefox would be a problem.
(I've never used a CAC, so this might be a dumb question.)
When you click through, you'll be directed to a page that, via standard SSL, requests a client certificate which triggers the browser prompt. At this point, you insert your CAC and select the certificate it contains. After you enter your PIN to unlock the certificate, your browser sends your client cert back and the site verifies that your CAC was issued by the CAC CA and that it hasn't been revoked, then HTTPS proceeds as normal.
The trick is that CAC certificates can't be used blindly, since you have to enter your PIN every time it gets used in a new session. Public sites can't just request a client cert without triggering the prompt and making you re-enter your PIN, and typically the CAC isn't inserted when you're not using DoD sites or on the DoD VPN.
I didn't know that. Worrying as, as stated, a lot of enterprises do depend on them. Is there a suggested alternative?
If you want something that matches X.509 client certs closely, WebCrypto + localStorage + either an extension or a static site (to host the JS that can get access to your localStorage and sign a site-specific token) ought to work, though I'm not sure I know of any out-of-the-box implementations. Mozilla Persona is essentially this, although since it's a somewhat different use case it's probably not an out-of-the-box thing.
Google would probably encourage you to use FIDO UAF. https://fidoalliance.org/specifications/overview/
Loading this into the browser is often desirable for access to the proxy API.
(I've even heard of people looking at polyfilling client certs with an implementation based on WebCrypto and localStorage.)
Yes, you can set things up on the server side so that it hits a static page instead of your web application. But you can do that with the JS-based solution too: have it send you to a login page with a signed query-parameter or similar, and verify that query parameter in the web server configuration. If it fails / doesn't exist, deliver a static site that includes the necessary JS to do the login.
Your web server will need to verify a signature or MAC there, but this is way less attack surface than the usual client-cert processing code in SSL stacks (which processes untrusted keys and signatures). Removing that code will be an equal or greater security win.
Basically, if there is interest in engineering a good application-level solution instead of relying on the transport-level one, it can absolutely be done. (I do freely admit there isn't anything that can be used out-of-the-box today, to my knowledge.)
But in any case, I'm not sure I understand the threat model of that. The <keygen> service will already sign any public key that gets to it past authentication, so if you're worried about client attacks, that's already a problem. There's no distinction between compromising an existing private key and getting a new, unauthorized private key signed. You're already requiring that the site be secure against these attacks.
Obviously you don't store this in storage accessible to every relying website; you just store it in the origin of the authentication service itself, and have it generate signed messages (either client-side or server-side) that get passed to the relying websites.