Developer’s Guide

Implement Account Chooser on a Site

AccountChooser is a facility where people can store identities they want to use for logging into Web sites. These are keyed by email addresses and (optional) identity providers. Your site can use AccountChooser automatically and for free, to help people log in more easily.

Although the process includes redirects through accountchooser.com, the account information is saved in the browser using HTML5 local storage. At no time is any user information stored on any server.

Meet ac.js

It’s all done with a chunk of JavaScript called “ac.js” which does a variety of things depending on where it’s called from, and can be customized with configuration arguments. This document walks through how to use ac.js; details about the entry-points and arguments are specified in “Account Chooser API” .

You could host ac.js yourself, but it’s probably best to pull it in from https://accountchooser.com/ac.js—remember to use secure networking. This document, and the sample apps, should give you enough information to get started with ac.js1.

In this document, when you see something like “login screen (loginUrl:/account-login)”, that means that ac.js has a notion of a “login screen”, named in config variable “loginUrl”, whose default value is “/account-login” (you can change that default). We give the short names of config variables in this document; they are stored in an object named accountchooser.CONFIG.

Without AccountChooser

Let’s assume you have a Web app with a database. In your database, you store per-account information; email, real name, maybe the user’s pictures, and then per-user application data. You have a way to check if a user-provided login and password correspond to what’s in the database. Presumably you have a login screen and a sign-up-new-user screen.

Also, you may be a RP (relying party) for an IDP (identity provider), and for certain accounts, dispatch to the IDP to perform login.

To help us walk through all this, we’ve created two separate open-source sample apps, FavColor and AccountChooser Guestbook. FavColor is a simple app (written in Ruby, based on the Sinatra framework), which stores one fact about each user: their favorite color. It provides a simple JavaScript control so they can update their favorite color.

AccountChooser Guestbook is a refactoring of App Engine’s sample Guestbook app, removing the Google user integration and replacing it with AccountChooser. It’s written in Java.

Here are links to the core accounts/identity logic, without the benefit of AccountChooser, in FavColor and AccountChooser Guestbook. If you’ve ever implemented an accounts/identity module, the logic will be familiar.

Storing Account Info in AccountChooser

There is some point in your app which recognizes the situation that a user has successfully logged in. Likely it occurs twice: Upon successful user login, and upon successful creation of a new user account.

When this happens, you need to return a page which invokes ac.js and uses the storeAccount feature instructing it to store the account info. If the login info was provided via AccountChooser, this is a fast, efficient no-op.

Diagram illustrating flow described below

The page you return will not actually be displayed, so its content is immaterial; you just need enough of a wrapper to provide a <head> element so ac.js is run. The invocation should look like this:

<script type="text/javascript"        
     src="https://www.accountchooser.com/ac.js">
</script>
<script type="text/javascript">
  accountchooser.CONFIG.storeAccount = {
    email: "nikhil_corlett@yahoo.com",
    displayName: "Nikhil Corlett",
    photoUrl: "https://example.com/nikhil_corlett.jpg",
    providerId: "identity.example.com" };</script>

If AccountChooser doesn’t already know about this user, they’ll see a screen like this and be queried as to whether they want to store the details to facilitate further logins:

Screenshot of AccountChooser.com. User can decide if they want to store their details for later.

Whether or not the user visits this AccountChooser screen, and whether or not they agree to store their account name, they’ll be redirected back to your app’s home screen (homeUrl:/).

You can see the changes required to add AccountChooser account info storage to FavColor and AccountChooser Guestbook Step One.

AccountChooser and the Login Screen

Now let’s put the stored information to good use. You need to call ac.js from your login screen (loginUrl:/account-login), for example by embedding this in your <head> element; note that this invocation also changes the default location from /account-login to /utils/mysitelogin:

<script type="text/javascript"
     src="https://www.accountchooser.com/ac.js">
</script>
<script>
 accountchooser.CONFIG.loginUrl = "/utils/mysitelogin";
</script>

Checks to see if there are any stored identities

ac.js will check to see if it has any stored identities; if there are none, the login screen loads and proceeds without any interruption. If there are any, the user will see a screen like this, and can pick one of the accounts listed there by clicking on it.

AccountChooser.com showing accounts that the user has stored for easy selection.

If the user clicks on one of the accounts, ac.js sends an HTTP POST to a status checker (userStatusUrl:/account-status) that you have to implement. The status checker will receive up to four arguments as URL query parameters.

At minimum, the checker will receive email ("email"). In addition, it may also receive a human-readable name ("displayName"), picture ("photoUrl"), and Identity Provider ("providerId").

If they picked the example account we just stored, your status checker would see “email=nikhil_corlett@yahoo.com”. Your status checker should return JSON saying whether or not you know that identity already:

  • {"registered":true} means you know the identity; i.e. you've registered the user and have a password stored for them on your site that they could log in with.
  • {"registered":false} means you don’t know that identity, so probably you want them to sign up to get a password on your site.
  • {"authUri":"IP-uri"} means that for that identity, you rely on an Identity Provider and the user should be redirected to the provided IP-uri which will start the appropriate federation protocol with that IDP. In this case ac.js will dispatch to that URI, and the subsequent login path depends on how that provider works. You can be guided by the IDP selection given by ac.js, but it’s not compulsory.

Known/Unknown

If you returned true, ac.js redirects back to your login page, looks through the DOM and finds the email field by its ID value (username:email), fills in the identity key, and places the focus in the password field, found via its ID value (password:password).

If you returned false, ac.js will redirect to your signup page (signupUrl:/account-create). This page should also call ac.js exactly as the sign-in page does, which will fill in the e-mail and display the user’s human-readable name (displayName:displayName) and picture (photoUrl:photoUrl) if those things are on file at AccountChooser. Then it’ll place the focus in the password field.

Depending on the value returned by the status checker, the user will get redirected to different pages that you define.

You can see the changes required to add AccountChooser login assist to FavColor and AccountChooser Guestbook Step Two.

Identity Provider Filtering

When you redirect to ac.js from your login page, you can optionally provide a list of Identity Providers that you support. Without this list, the user will just see a list of email addresses they can select.

However if you do include a list, when ac.js redirects back to your account-status page, you can be sure that, should it identify a provider, that provider will be from the list you provide. For example:

<script type="text/javascript"
     src="https://www.accountchooser.com/ac.js">
</script>
<script>  
  accountchooser.CONFIG.providers = ["yahoo.com", "facebook.com" ];
</script>

Change Management Process

From time to time, the Account Chooser Working Group may decide to make changes to Account Chooser. To keep abreast of upcoming changes, it is important to subscribe to the mailing list oidf-account-chooser-announce.

The change management process for Account Chooser is:

  • Requirements proposal
    New ideas are discussed on the main working group mailing list and at the bi-weekly phone calls. Once requirements have been defined and there is consensus to move forward, development will begin.
  • Prototype implementation on accountchooser.biz
    Changes will be pushed to accountchooser.biz and announced at oidf-account-chooser-announce. The announcement will describe the changes and contain a target date to be pushed to the beta channel. If there are significant bug reports or feature modifications requested, the target date will be revised. It is important to note that accounts that are stored in Account Chooser will not be visible at accountchooser.biz because account entries are saved in HTML 5 storage by domain.
  • Pending release candidate at accountchooser.com/beta
    Developers can choose to direct to their sites to the beta channel for their production environment if they want to take advantage of the latest enhancements. Unless significant issues are reported, the beta channel release candidate will be pushed to the stable channel after two weeks.
  • Stable release at accountchooser.com
    All pushes to the stable channel will be announced on oidf-account-chooser-announce.
If you'd like to participate in the discussions about how to improve Account Chooser, please subscribe to the working group mailing list and share your ideas.

That’s All!

By adding simple Javascript callouts to a handful of places in your existing code and adding one new endpoint, without much re-architecting, you’ve added AccountChooser function, saving your users some keystrokes, and probably cutting down on the number of fumblefingered failed login attempts.

Additional Resources


  1. The ac.js source code is online; the full API provided by ac.js is documented, and there’s a write-up of the JavaScript implementation.