Reminder for people who try and think it’s a bug: Persona, on this site, is for me to be able to log in and post entries. As such, you will not be able to log in to this site, since you don’t have an account and can’t create one. This isn’t a bug, it’s intended functionality — site owners can control whether accounts can be created, and by whom.
So, last week I mentioned in passing that my next project for this site would be implementing Persona for authentication. Since I work at Mozilla, I’ve had some exposure to it already in real projects — on MDN we switched to Persona a while back, when it was still being called “BrowserID” — and, though I have a long history of being skeptical of federated-identity and single-sign-on systems, Persona has finally changed my mind.
Also, as of a couple days ago, Persona is the sole authentication system for this site. I’ll get to how that was accomplished in a bit, but since Persona is still a pretty new thing I figured I’d take a moment, first, to explain just what Persona is, and why it won me over in the end.
Now, you may have already seen some basic explanations of Persona. For the most part they tend to focus on the end-user benefits, specifically:
- Your email address is your identity. This is something you probably already have, and probably already use as an identifier.
- When you use Persona to sign in to a site, you are not transmitting a password to the site, and in fact the site never stores a password for you.
That last one is a big deal, in this age of password breaches, since it means you don’t have to make up a bunch of passwords for different sites, and you don’t have to trust a bunch of sites to safely store passwords. When you get right down to it, Persona doesn’t actually require any passwords. But to see why, we need to actually look at what goes on.
How it works
With as little spec language as possible (you can read the full documentation over at MDN if you really want that), here’s what Persona actually does: it’s a simple, usable, implemented-in-the-browser application of public-key cryptography. No, really.
Persona starts with you, the user. You have at least one email address; you can have more if you want, and use each one as a separate identity. For each email address you’re using, you’ll have an identity provider, which is just someone who’s willing to vouch for the fact that you are someone who controls that email address. Your identity provider can be you (if you manage your own email and want to run your own provider), or it can be your email provider, or it can be Mozilla’s fallback provider at persona.org, which confirms that you control an email address by sending a verification message to that address.
- An expiration date (must be within 24 hours of being issued),
- The domain of the identity provider who issued the certificate,
- The email address you’re using,
- The public key your browser submitted for it, and
- A signature, generated by the identity provider’s private key.
- This is in fact the site you’re trying to sign in to.
- The certificate issuer’s domain matches the email address domain, or is
- The certificate hasn’t expired.
- The public key contained in the certificate verifies the signature on the assertion.
- The identity provider’s public key (there’s a protocol for fetching that) verifies the signature on the certificate.
If those checks pass, you’re signed in. From there, you might just do stuff that’s identified with your email address, you might create a more detailed profile if you like (and if the site offers that), etc. etc.
Why it’s cool
First of all, yes, unlike OpenID this is based on something most people on the Web already have: an email address. That’s a big win right off the bat. More importantly, the way Persona is constructed means that it offers some very interesting options for user privacy. For example, your identity provider does not necessarily know what sites you’re signing into, because the only thing they see from the site is a request for their public key. All they know is that someone for whom they’re the provider is signing in, and it should be relatively easy to set things up such that it’s not possible to match that event up to a specific user through traffic analysis (i.e., a request from this user for a certificate, immediately followed by a request from a site for the public key).
That stuff is a ways down the road, though, since there are very few identity providers right now, and most sites that implement Persona aren’t actually doing verification on their own servers; they’re doing it through Mozilla’s remote-verficiation API at persona.org (meaning, if Mozilla is your provider, and the site you’re signing into just uses the remote API to verify you, then Mozilla can see that it’s you signing in to the site — the verification API basically just lets sites post over the certificate and assertion, and get back a response indicating whether the checks pass).
Also of interest is how wide-open the process of authenticating with your identity provider is; for example, when I use my
@mozilla.com email address, I’m authenticated through Mozilla’s LDAP system. The persona.org service also has bridges which take advantage of existing authentication systems used by email providers. The first rollout supported Yahoo email, and now Gmail is supported as well. And that’s really just the start; while it would be awesome to have lots of proper identity providers running around, it’s also possible to support a ton of people, through their email providers, via these kinds of bridges.
How I set it up
The easy way to get Persona auth in Django is with django-browserid, which does offload to the persona.org verifier rather than doing verification on its own (there’s been talk of integrating PyBrowserID support, since it implements a local verifier), so there’s a minimum of crypto libraries needed (in fact, none). The name, as mentioned earlier, is from the very early days when Persona was still internally referred to as “BrowserID”.
As it turns out, django-browserid has some pretty good documentation, and is almost stupidly easy to work with. I had to put in a bit of extra effort since Python 3 support is being worked on (hence I’m deploying off a fork where I’ve cleaned that up), but since all the Django-y bits of my site are in a public repository you can see the commit that added Persona, and it really is not much code at all. The only thing I needed beyond that was to add the following in my local settings on the server:
SITE_URL = 'http://www.b-list.org' LOGIN_REDIRECT_URL = '/' BROWSERID_CREATE_USER = False
SITE_URL setting is required for Persona to work, and has to match where your site is running. And
BROWSERID_CREATE_USER lets you enable or disable automatic creation of new accounts for email address which don’t match any existing
User in your database; since I’m the only user here, and already have a
User matching my email address, I want that turned off.
I also popped open a Python interpreter, fetched my Django
User instance, and called its
set_unusable_password() method, since I’m never going to use a password on it ever again.
And… that’s it. Really. Everything Just Works™, including sign in, sign out, the admin, everything. It really was almost stupidly easy, which is the way authentication should be.