Now that Resteasy 3.0-beta-1 is out, I’ve been thinking a lot about some custom security protocols I’d like to prototype. Client cert authentication has always been a part of that thinking, but when it comes to browsers, client certificates are complex and even scary for most users. Why does it have to be this way?
Current web authentication uses cookies to set up a secure session between an authenticated user and his browser. Cookies are allocated and stored per-domain and forwared with HTTP requests to those domains. Why can’t we do something similar with SSL and client certificates?
For example, what if when you registered at Google.com, it asked you, “Do you want to authorize this device?”. You would click on a “OK” button and Google would generate a key-pair and a digitially google-signed certificate for your device. The HTTP response to clicking that “OK” button would provide a base 64 encoded headers that contained the generated private key and signed certificate:
HTTP/1.1 200 OK Content-Type: text/html Set-Private-Key: 23423ab1123affaccde12312 Set-Certificate: 11ab332789dff <h1>All Set</h1> <p>Your machine is now authorized</p>
For the google.com domain, your browser would store the private key and certificate in your browser’s persistent store. The next time your browser makes an HTTPS connection to google.com, it would use this certificate to connect. When you think about it, this isn’t much different than google setting a persistent cookie to remember who you are. Now its remembering you in a much more secure way.
Additionally, what would be cool, if this google-generated client-cert could be negotiated and sent to other domains/websites on the internet. For example, let’s say you had a social media site that exchanged sensitive information and wanted to use HTTPS. The social media site could send a redirect, with an additional certificate negotiation header stating which client-cert domains it prefers
HTTP/1.1 307 Location: https:/.../ Accept-Certificate: google.com, facebook.com
Here, the server is redirecting us to an HTTPS based URL. The Accept-Certificate says that it requires a google.com or facebook.com generated client certificate. The browser would then make an SSL connection to the redirect URL using a stored client cert from one of the preferred domains.
There’s a bunch of cool things about this. For one, you could have SSO to multiple different social media sites and applications without the need to enter one password. Secondly, there’s a lot of secure protocols you could implement on top of this to make the internet as a whole, more secure. Most importantly, there’s no knowledge the human user has to have as to install a client certificate. It really sucks that the microsofts, mozillas, apples, and googles of the world haven’t put much more thought into client-certs and making them easier to use.
Nov 07, 2012 @ 11:15:34
Sounds like a good idea, but if the certificate is a real certificate you need to send it to the client, which is more than just the key pair. Also “Accept-Certificate” sounds a bit limiting, because the idea behind certificates is that ultimately they can be trusted to have been signed by a trusted set of certificate authorities, so in theory you should accept any client certificate. Now in practice it may be different, I agree.
Nov 07, 2012 @ 18:47:12
I do send the ‘real’ signed certificate to the client in the Set-Certificate header.
I also disagree Accept-Certificate is limiting. In fact, its actually *useful* instead of our current state of affairs. The idea behind this is that a specific domain can establish identity via a specific client certificate for that domain. And also avoid having the human user having to know/install/config anything. Its no different than an automatic login via a persistent cookie, except that the certificate can be forward to multiple different domains.
Nov 07, 2012 @ 12:48:36
Check BrowserID protocol (https://developer.mozilla.org/en-US/docs/Persona/Protocol_Overview). I think the idea behind it is quite similar.
Nov 07, 2012 @ 18:53:49
Quick look Persona leaves me with these impressions:
* Its still user driven, rather than server-driven. Meaning the server doesn’t initiate certificate creation in this protocol.
* The assertions look a lot like SSL with client verification.
In the protocol I’m proposing, the server can tell the client to store a certificate, much like it can ask the client to store a cookie. But, unlike a cookie, this cert can be used to establish SSL connections with different domains.
Distributed Weekly 180 — Scott Banwart's Blog
Nov 09, 2012 @ 09:17:19
Nov 27, 2012 @ 16:36:06
For user driven – Microsoft tried an approach with Information Cards that were baked in Vista. http://en.wikipedia.org/wiki/Information_Card
I am not sure the concept was a huge success.
With your server side approach, it may work as long as Browsers implement a temporary key store to which the user can authenticate. If not, what difference does the browser make when Bill uses the browser and next Bill’s friend uses the same browser to access google and performs some sensitive operation. Server side you also need people to agree to store the keypairs for all the browsers that have registered with them. Economically and scale wise, there are challenges.
Nov 27, 2012 @ 16:53:35
Anil, how are your concerns any different than a website setting a persistent cookie to use as authentication? i.e. how jboss.org and our JIRA currently work? What I’m basically suggesting is a way to assign identity to your browser securely. For the browser applications that require greater lockdown, the user would enter credentials in addition to client-cert auth.
Dec 03, 2012 @ 23:04:39
Very nice, wish I had read this sooner. It covers the very important issue of distributing client certs. I posted a question related to this on stack overflow, http://stackoverflow.com/questions/12966460/rest-apis-and-message-level-security.
Not many people are actively tackling the issue of key-pair security outside of SAML and/or WS-* (a.k.k ws-death star).
I ended up using detached CMS signatures passed in custom header to overcome issues with SSL accelerators.
It would be really cool if browsers supported easy CSR requests out of the box to handle server challenges. BTW, moving all new apps to RestEasy 3.x+ keep it coming…