lloyd.io is the personal website of Lloyd Hilaiel, a hacker who works for Mozilla, lives in Denver, and is interested in web technologies.

All the stuff you'll find here is available under a CC BY-SA 3.0 license (use it and change it, just don't lie about who wrote it). Icons on this site are commercially available from steedicons.com. Fonts used are available in Google's Web Font directory, and I'm using Ubuntu and Lekton. Finally, Jekyll is used for site rendering.

Finally, Atul, Pascal, and Stephen inspired the site's design. And in case you're interested, this site's code is available on github.

How BrowserID Works
2011-07-01 00:00:00 -0700

(a special thanks to Mike Hanson and Ben Adida for their careful review of this post)

BrowserID is a decentralized identity system that makes it possible for users to prove ownership of email addresses in a secure manner, without requiring per-site passwords. BrowserID is hoped to ultimately become an alternative to the tradition of ad-hoc application-level authentication based on site-specific user-names and passwords. BrowserID is built by Mozilla, and implements a variant of the verified email protocol (originally proposed by Mike Hanson, and refined by Dan Mills and others).

Before learning the technical details of BrowserID, it's recommended you experience a user's perspective of BrowserID with the myfavoritebeer.org demo, and then work through the integration tutorial for a website developer's perspective.

This post aims to provide a readable technical overview of the system. First it will summarize the key design elements of BrowserID. Next, it will explore the various actors in the system and their inter-relationships. Finally, we'll walk through several of the most important flows, including certificate provisioning (where the user obtains authentication material from an identity provider), assertion generation (where the user uses that material to tell a website who they are), and assertion verification (where the website being logged into verifies the user's email address).

BrowserID Features

Perhaps the best way to begin understanding BrowserID is to walk through its key design features:

Mechanism

BrowserID uses asymmetric cryptography and digital signatures to allow browsers to create signed assertions about the user's identity, and by identity providers to vouch (via signing of a key-email pair) for a user's identity in a disconnected fashion. BrowserID uses cross document messaging to communicate between documents served from different domains, which makes a usable implementation of BrowserID possible right now without modifications to existing browsers.

Actors

As said above, BrowserID is decentralized, which results in several actors interacting under a healthy mutual distrust. These actors include:

Important Flows

A solid understanding of how BrowserID works can be attained by working through the main flows of the system, in terms of the interactions between the actors defined above. This section will walk through the three most important flows:

Certificate Provisioning

Certificate Provisioning is the process by which a primary (like gmail.com) verifies that a user owns one of her email addresses (like lloydhilaiel@gmail.com) and provides them with a signed certificate that vouches for their ownership of that email.

Visually, the flow looks like this:

Certificate Provisioning

The actors involved in this flow include the user, her browser (which happens to have BrowserID support built in), and her email provider gmail (who in this case happens to be a BrowserID primary identity authority).

  1. Some event occurs whereby the user indicates that they'd like to log into an RP using their gmail address, and the user is directed to a web-page on gmail.com designed for the purposes of key provisioning.
  2. The user authenticates to gmail using their user-name and password. (or, perhaps, a stronger authentication scheme - the strength of this login is entirely up to the authority)
  3. gmail-hosted javascript invokes navigator.id.genKeyPair(), a client side function implemented by the browser, that causes a key-pair to be generated. Upon the completion, the public key is returned to the callee (gmail's javascript), and the key-pair is cached by the browser for the duration of the session.
  4. gmail's javascript code on the client sends the public key up to a gmail server over SSL.
  5. gmail signs the user's email address, the public key, and a validity interval generating a certificate in the form of a JWT (which is just a means of encoding a signed JSON object).
  6. gmail returns this signed bundle of information, AKA the certificate, to the client as a response to the request in step 3.
  7. JavaScript code served from gmail invokes navigator.id.registerVerifiedEmail() on the client passing in the certificate.
  8. The browser locates the private key generated in step #2 and moves it and the certificate from temporary session storage into the user's BrowserID key-ring. The user now has a valid certificate from gmail stored in their browser which they can use to generate assertions proving their identity.

Users will encounter certificate provisioning anytime they wish to use an email to log into a site that they haven't used recently on their current browser.

The flow above assumes that the primary (gmail) has built custom BrowserID support. In practice, BrowserID must handle the case where an email provider hasn't (yet) built such support. In this case browserid.org manually verifies email addresses and acts as a secondary authority (itself issuing certificates for email addresses which it does not control).

Finally, in the flow above the browser has native support for BrowserID, exposing functions to generate key-pairs and store certificates. In the absence of such support, BrowserID provides a small JavaScript shim that implements the missing functionality using standard HTML5 techniques and cryptographic routines implemented in JavaScript.

Assertion Generation

Assertion Generation is the process by which a user's browser produces an assertion that proves that a user owns a given email address.

  1. During the process of logging into a website, the user clicks on a "sign in" button on the RP's site, causing the RP to invoke navigator.id.getVerifiedEmail().
  2. The user selects an email address that they would like to use to log in from a list rendered by the browser.
  3. The browser combines the domain requesting the identity (the audience) and a validity period into an an assertion. The assertion is signed using the private key associated with the identity and encoded into a JWT
  4. The signed assertion is combined with the previously signed certificate associated with the identity in to a bundle (the certificate includes a public key, and the email address being shared).
  5. The bundle is then returned to the web page.

The result of assertion generation is a JSON structure which looks like this:

{
  "assertion": {
    "audience": "myfavoritebeer.org",
    "valid-until": 1308859352261
  }, // signed using lloyd's key for lloydhilaiel@gmail.com
  "certificate": {
      "email": "lloydhilaiel@gmail.com",
      "public-key": "<lloyds-public-key>",
      "valid-until": 1308860561861
  } // certificate is signed by gmail.com
}

At the completion of this flow, the browser has provided the RP with an email address that they can verify is owned by the user. See the next section for how the verification process works.

While the flow above describes the case where native browser support exists for BrowserID, the flow is identical (except for the user interface) when the browser does not have native support: In this case all of the required functionality can be supplied by a JavaScript shim.

Assertion Verification

Assertion Verification is the process by which a Relying Party can verify that an assertion of a user's ownership of a certain email is valid. Verification looks like this:

Assertion Verification

  1. The RP (securely) fetches the bundle containing both the assertion and the certificate from the client to her servers.
  2. Validity periods are checked on both the certificate and the assertion.
  3. The RP extracts the host-name of the email address within the assertion; this is the primary identity authority for the email address. In our example above, it's gmail.com.
  4. Public key(s) for gmail.com are obtained from a well-known location on their servers (specifics TBD).
  5. The certificate signature is verified using the public key(s) obtained from gmail.com; success proves to the RP that the user's public key, which is embedded in the signed certificate, is valid.
  6. The assertion signature is then verified using the user's public key embedded in the certificate, after which point the RP knows the assertion is valid and the user owns the specified email address.

At the conclusion of the assertion verification flow, the RP has a verified email address for the user.

The above flow assumes that the primary identity authority supports BrowserID; specifically, that the authority provisions certificates and publishes their public keys on their site. In the case that the email that is the subject of the assertion is not from a domain where BrowserID support is present, then the assertion certificate will include an issued-by property that is the domain of secondary authority: the entity that has vouched for the validity of the email address. The common case today is that this will be browserid.org, but in the future there may be a small number of secondary authorities run by browser vendors or trusted organizations. RPs are explicitly asked to trust these authorities for email verification, so their processes and operational security would need to be transparent and of the highest quality.

In a future where BrowserID is widely adopted, secondary authorities are the exception rather than the rule. Identity issuers would be directly responsible for the security of their own users.

Implementation Status

At the time of writing browserid.org is a partial implementation of the system described here. The key differences between what is described and what exists are:

Differences from the Verified Email Protocol

This post exists to provide a clear description of how BrowserID works, and also to precisely express the ways that it is different from various different implementations of the same theme. BrowserID is a simplification of the protocol originally proposed by Mike Hanson, having two key differences:

Secondaries de-emphasized.

The original proposal emphasized the distribution of secondary identity authorities more than BrowserID does. There are significant UX and administrative challenges in supporting distributed secondary authorities, and with BrowserID the thinking is that it is better to focus on encouraging email providers to include BrowserID support than it is to create a new ecosystem of secondaries, which may ultimately be detrimental to the safety and usability of the system.

No webfinger based assertion verification

The original proposal included two different ways for an identity authority to vouch for a user's identity. The first method was as in BrowserID, via a cryptographic signature. The second method was for the authority to publish the user's current keys via webfinger and in this way vouch for them.

The latter approach is omitted from BrowserID because it is perceived as both reducing the privacy of the system (RPs would ultimately leak more information back to identity providers about the user's activities), and because it increases total system complexity.