title: Using client certificates in place of passwords on a public web app
body: <p>I have a web app where anyone can register for an account. Instead of passwords, I'd like to use client certificates for authentication. Is this practical?</p>
  
  <p>It seems like there are a lot of problems:</p>
  
  <ul>
  <li><p>How do you generate a keypair in a cross-browser way? <code>&lt;keygen&gt;</code> seems useful, but I need to support Internet Explorer.</p></li>
  <li><p>How do you sign the keypair and get a certificate into the browser? Every explanation of client certs only includes openssl commands to generate a certificate. I really don't want to shell out to openssl from my web application.</p></li>
  <li><p>Since the server is signing certificates, what if its signing (CA) key is compromised? This seems to be a more serious attack than a password database leak, because the attacker can silently impersonate any user forever.</p>
  
  <p>I'd like to avoid signing a certificate at all, and use the just the public key fingerprint as the user's identity. This means that knowledge of the CA key can't be used to impersonate anyone, because they don't have users' private keys.</p></li>
  <li><p>It seems like someone should have done all this before. Is there any open-source implementation of the whole end-to-end process? A Python or Django implementation would be particularly helpful.</p></li>
  </ul>
  
  <p>Here's what I think the process would look like:</p>
  
  <ol>
  <li>While the user is signing up, their browser generates a keypair and sends a signing request to the server.</li>
  <li>The server immediately returns with a signed certificate that gets loaded into the browser. The server stores the key fingerprint in the database to authenticate the user later. I don't want to use the certificate DN as the authentication, see above about CA compromise.</li>
  <li>The frontend webserver requires clients certs, validates them, and sends the public key fingerprint to my app server.</li>
  <li>The app server looks up the user by their key fingerprint, and are now authenticated.</li>
  </ol>
  
  <p>I don't want to deal with certificate revocation. Since the key fingerprint is used to authenticate, not the certificate DN data, just changing the fingerprint associated with a user will force the use of that key.</p>
  
  <p>EDIT: I was able to find a demo implementing a similar workflow: <a href="https://openweb.or.kr/html5/index_en.php" rel="nofollow">https://openweb.or.kr/html5/index_en.php</a>. It doesn't work in IE, and has the CA problems I talked about.</p>