One Time Passwords

Webmaker users currently sign in to their accounts using Persona, Mozilla's privacy respecting authentication system. It's fairly simple, and has worked really well since our rewrite this past march. You can read the details of the implementation in the blog post I've just linked.

Today, we're experimenting with alternative methods for users to log in and sign up. One such method, which Matthew Wilse has built prototypes for, has been called the "Passwordless" or "Handshake" method. I would argue that calling the system passwordless is a bit misleading and that handshake is not clear about what it really is, so I'll refer to it from here on out as the One Time Password(OTP) system.

For the past several weeks I've been building this system into existing Webmaker applications. We're hoping to deploy it to a limited number of people and gather some feedback and statistics, particularly whether or not it improves successful signup/signins (Persona is great, but a lot of users just give up trying to make it work).

Another benefit of the work I've been doing is a huge improvement on the account creation process. Here's some background on how it currently works:

1: A user clicks "Sign Up" somewhere on Webmaker
2: A persona pop-up appears
3: A user who does not have a Persona account must now create one. If they have one already, Go To 5
4: Verify email with Persona.org
5: Sign into Persona
6: A new user modal pops up, Asks for a username, among other things.
7: Yay, a new user!

At every step above number 7, some significant percentage of users just simply gives up. I don't blame them, it's incredibly confusing to have to create two accounts as well as verify an email address.

Matthew's prototypes provided a sign-up flow that looked a little bit like this:

  1. A user clicks "Sign Up" somewhere on Webmaker
  2. They provide an email and a username
  3. Yay, a new user!

Wow, that sounds really nice! So I'Sign up GIF](GHOST_URL/content/images/sign-up.gif)

I've also made the OTP sigSign In GIF](GHOST_URL/content/images/sign-in.gif)

During the early stages of this work, I build the front end bits as best I could, but my CSS-Fu has never been that strong. Recently, Ricardo Vazquez has come on board the login train to make the prototype modal dialogs beautiful to see and use. Stay tuned to my blog and Webmaker demos in the near future to see the project evolve!

How OTP's work

Here's a list of steps that describes the whole One Time Password protocol (shown above, second image), from start to end.

  1. The User-Agent POSTs: { email: "chris@example.com" } to /auth/v2/request on the app server (lets use webmaker.org)
  2. The Webmaker.org server should forward the post body to the Basic Auth protected route /auth/v2/request on login.webmaker.org
  3. The login server will look up the user account by the provided email address. If none is found, responds to the request with a 400: "User not found"
  4. A one time password is generated using Hat.
  5. The password is 24 random bits and is converted to base 36. This generates a five character string of letters and/or digits.
  6. The password is set to expire thirty minutes after creation, and is passed to Webmaker's event processing queue Sawmill. Its powered by Amazon's Simple Queue Service (SQS), and messages are sent using Hatchet, which uses Amazon's aws-sdk module.
  7. From Sawmill, The event is converted into an email using a template, and is forwarded to lumberyard
  8. Lumberyard sends the email to the one stored in User account the OTP was generated for. This uses the aws-sdk and Amazon's Simple Email Service (SES)
  9. Once the User gives the User-Agent the OTP it POSTs: { email: "chris@example.com", token: "s34xa" } to /auth/v2/authenticateToken on the app server
  10. The Server will forward the post body to /auth/v2/authenticateToken on login.webmaker.org
  11. The login server will attempt to fetch the user and login token from the database, ensuring that the fetched token was 1. created no more that thirty minutes from the system time on the server and 2. has not been used to log in already.
  12. Should the criteria not be met, a 401 reponse it returned to the app server, who should not issue a session cookie.
  13. If all criteria is met, the token is marked used and saved, and the user account object is serialized into session format and returned to the app server.
  14. The app server should then send a SET-COOKIE header to the User-Agent. It should be set to https only and be encrypted with a session secret.

What Now?

With the code in a working state, it's just a matter of iteration. Code review, fixes + optimizations, repeat. We also have folks working on copy for the emails and modal dialogs. One thing that I think is going to be the most challenging for us when we roll out the new system is clearly communicating to users the new changes. Whether it be through email comms, banners on the homepage or a first-run log-in experience, I feel it's incredibly important to get this right.

We've been thinking about keeping Persona as an optional log-in method (+1) and implementing an opt-in, run-of-the-mill password login system (I have implemented this fully, but it was cut from this iteration D:). I've also experimented (successfully) with turning login.webmaker.org into an OAuth2 provider - but havent actually gotten any resources or scopes set up to work with the oauth tokens I can generate.

I've also reached out to the security gurus in the organization, with the goal of going over the new protocol with them and getting feedback on the right and the wrong.

That said, what do you think? Have you had experience with log-in flow like this? What challenges did you face or forsee this flow facing? Feel free to use the comment section below, drop some comments in the Bugzilla bug or email me