Treehouse

An Introduction to Persona

By on  
Mozilla Persona

So you've heard of this new hipster login service called Persona. It promises to relieve you of dealing with passwords, and be easy to setup. Can it really? I'm here to walk you through setting up Persona on your own website, in just a few minutes. At a glance, here's what you'll need to do:

  1. Grab the include.js shim
  2. Hook up your login button to use navigator.id
  3. Verify the credentials navigator.id gives you on your server

So let's dive in, step by step.

include.js

Until Persona is native in all browsers, you'll need to include a shim that provides the navigator.id API in all browsers. While Persona is in beta, we recommend linking directly against our server. Once we feel confident that the internals are exactly the way we want, we can encourage people to self-host. So, throw this at the bottom of your <body>:

  <script type="text/javascript" src="https://login.persona.org/include.js"></script>

Using navigator.id

A Button

If you don't already have a login button, then add one in your markup. We provide some buttons that already look quite swell.

navigator.id.request

I'm going to assume you use jQuery, because most do. If you use something else, then you should know what parts to change.

$("#login-btn").click(function(e) {
    e.preventDefault();
    navigator.id.request();
});

navigator.id.logout

When a user is logged in, you can show a logout button instead, and hook it up like this:

$("#logout-btn").click(function(e) {
    e.preventDefault();
    navigator.id.logout();
});

navigator.id.watch

Next, we can start watching for changes in the declared identity. With this method in place, if a new user has closed your site while confirming their email address, we can still forward them back to your site, and you will receive an onlogin event. There's a few other good reasons, but that's likely the most common.

We do this with navigator.id.watch(). It takes an onlogin method, onlogout method, and a loggedInUser string. If you think the user is logged in, you should pass the email string, and we'll double check it.

navigator.id.watch({
    onlogin: function(assertion) {
         verifyAssertion(assertion);
    },
    onlogout: function() {
   
    },
    loggedInUser: undefined
});

The onlogin callback will be called with an assertion. This is a signed blob with data inside essentially saying "I promise this is [email protected]". Still, you can't fully trust the client. So, you need to send this assertion to your server, and verify that it wasn't tampered with, and that the promise isn't a lie. After successfully verifying, you can do your normal session stuff that you would normally do, and then be sure in all subsequent page loads to set loggedInUser to the user's email.

Verification

The verifyAssertion function shown in the onlogin callback above is a function you implement. Again, assuming jQuery, it could look something like this:

function verifyAssertion(assertion) {
    $.post("/auth/verify", { assertion: assertion }, function onSuccess(resp) {
         // maybe you return a json response including the email
         updateUser(resp.email);
    });
};

As with the shim, we currently recommend you ask our verification server to verify the assertion for you, but once we're certain theres no bugs in the verification process, you'll be welcome to self-host a verification method on your own server.

Our verifier service will return a valid JSON response if the assertion is valid:

{
    "status": "okay",
    "email": "[email protected]",
    "audience": "https://yoursitehere.com",
    "expires": 1308859352261,
    "issuer": "bar.com"
}

Here's an example using Python and the Requests library:

data = {'assertion': assertion, 'audience': 'https://yoursitehere.com'}
resp = requests.post('https://verifier.login.persona.org/verify', data=data, verify=True)
json = resp.json()
if json['status'] == 'okay':
    # use json['email'] to do your normal logging in
    # i made up a login mechanism here
    email = json['email']
    user = User.objects.get(email=email)
    if not user:
        user = User.objects.create(email=email)
        session.userid 
    session.userid = user.pk
    return { 'email': email }

If the assertion is valid, we logged the user in if we've seen them before, or create a new user if we haven't. You can imagine what you would do if resp.json['status'] was not okay.

That's it!

You've now got Sign Up and Sign In implemented. You don't need to worry yourself with hashing passwords, showing captchas, or any like matter. If you liked all that, here's some additional resources to learn more and get the most out of Persona:

Sean McArthur

About Sean McArthur

I’m a 25 year-old web developer in Orange County, California, trying to make logins on the Internet better.

ydkjs-6.png

Recent Features

  • Write Better JavaScript with Promises

    You've probably heard the talk around the water cooler about how promises are the future. All of the cool kids are using them, but you don't see what makes them so special. Can't you just use a callback? What's the big deal? In this article, we'll...

  • An Interview with Eric Meyer

    Your early CSS books were instrumental in pushing my love for front end technologies. What was it about CSS that you fell in love with and drove you to write about it? At first blush, it was the simplicity of it as compared to the table-and-spacer...

Incredible Demos

  • Create a Twitter AJAX Button with MooTools, jQuery, or Dojo

    There's nothing like a subtle, slick website widget that effectively uses CSS and JavaScript to enhance the user experience.  Of course widgets like that take many hours to perfect, but it doesn't take long for that effort to be rewarded with above-average user retention and...

  • Create a Dojo Lightbox with dojox.image.Lightbox

    One of the reasons I love the Dojo Toolkit is that it seems to have everything.  No scouring for a plugin from this site and then another plugin from that site to build my application.  Buried within the expansive dojox namespace of Dojo is

Discussion

  1. If I recall correctly in requests>=1.0 json is method, not property.

    • Ack, you’re right. I forgot the parens in the example.

  2. Please, post us a tutorial to use Persona in native apps of Android & iOS using WebView

  3. Thanks for the introduction of Persona and the instruction of installing!

  4. I’ve been waiting for this to get a release, but one thing I don’t understand is how it’s different to, say, openID, or OAuth? Is this not just another competing standard? http://xkcd.com/927/

  5. It seems as though you don’t collect any information other than the email address. Does this mean it is safe for schools to use Persona? I am thinking about the COPPA requirements.

  6. So you just check the ID of the browser software… thats not secure at all, no use ion shared computers, only good for mobile

  7. Interesting to see that they focus on privacy compared to openID. Will give it a try this weekend.

  8. Finally a good explanation of Persona, so even I can implement it :-)

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!