O'Reilly

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.

Track.js Error Reporting

Recent Features

  • CSS Filters

    CSS filter support recently landed within WebKit nightlies. CSS filters provide a method for modifying the rendering of a basic DOM element, image, or video. CSS filters allow for blurring, warping, and modifying the color intensity of elements. Let's have...

  • 7 Essential JavaScript Functions

    I remember the early days of JavaScript where you needed a simple function for just about everything because the browser vendors implemented features differently, and not just edge features, basic features, like addEventListener and attachEvent.  Times have changed but there are still a few functions each developer should...

Incredible Demos

  • Create Keyboard Shortcuts with Mousetrap

    Some of the finest parts of web apps are hidden in the little things.  These "small details" can often add up to big, big gains.  One of those small gains can be found in keyboard shortcuts.  Awesome web apps like Gmail and GitHub use loads of...

  • Fixing sIFR Printing with CSS and MooTools

    While I'm not a huge sIFR advocate I can understand its allure. A customer recently asked us to implement sIFR on their website but I ran into a problem: the sIFR headings wouldn't print because they were Flash objects. Here's how to fix...

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!

Recently on David Walsh Blog

  • OSCON Portland:  Conference  Discount!

    O'Reilly puts on the best web industry conferences in the world.  These conferences include Fluent Conference, Velocity Conference, and the upcoming OSCON in Portland, Oregon from July 20-24.  Open Source Convention (OSCON) is a conference that focuses specifically on open source developers and the tools and possibilities...

  • Follow Redirects with cURL

    I love playing around with cURL. There's something about loading websites via command line that makes me feel like some type of smug hacker, just like tweeting from command line does. I recently cURL'd the Google homepage and saw the following: I found it weird that Google...

  • Developers Have WordPress, Amateurs Have Squarespace, Professional Designers Have the NEW Webydo!

    Web design platforms have traditionally come in one of two varieties. There are the solutions like WordPress and Drupal that are incredibly powerful, but an understanding of web development and coding is required to be able to use those platforms effectively. On the other side of the...

  • Chris Coyierâs Favorite CodePen Demos II

    Hey everyone! Before we get started, I just want to say it’s damn hard to pick this few favorites on CodePen. Not because, as a co-founder of CodePen, I feel like a dad picking which kid he likes best (RUDE). But because there is just so...

  • GSAP + SVG For Power Users: Motion Along A Path

    Now that the GreenSock API is picking up steam, there are many tutorials and Getting Started guides out there to provide good introductions to the library, not to mention GreenSock’s own Forum and Documentation. This article isn’t intended for beginners, but rather a...