Tutorial: Automatically Authenticate Email Login Tokens With Rails & Devise
Codementor Ruby Expert Adam Derewecki is a former director of web engineering at ApartmentList.com, hacker at Causes.com, and one of the first technical leads at Yelp.com. Presently he’s bootstrapping his P2P camera rental startup, www.CameraLends.com, using Rails/Heroku.
This article was originally posted on his blog.
Building Automatic Login Tokens for Emails with Rails and Devise
When you build out your product, it’s important to listen to your what your users are telling you. But it’s more important to read between the lines to discover what the underlying problems actually are. For example, I’ve noticed that login is a problem on CameraLends: forgotten email addresses resulting in dupe accounts, signing up on desktop then clicking a reservation email from their phone, signing up via Facebook and trying to login with a password, and other variations. From my viewpoint looking over the entire ecosystem, it was pretty clear that automatic login links in transactional emails would alleviate much of the pain.
Automatic login links can be implemented by inserting a per-user secret token into the URL parameters. The back-end system to this can be simple or very complex, depending on your requirements. Some of the trade-offs I evaluated:
- How long should the login tokens work?
- Do we need to keep track of the last X tokens or just the most recent?
- Should links with tokens be automatically built, or specified on a
per-link basis?
For my purposes, I decided the simplest solution was a good place to start: only the last email’s login link would work, and adding the token to links in emails would not be automatic. We need to add one column token
to our User model:
rails g migration AddTokenToUser token:string
And then add a method to the User model that generates and stores new tokens:
Next, we need to create a before_filter that checks for the presence of a token and handles it:
At this point, we’ve got a barely-minimum viable product: from a Rails console, you can create a token for a user and then construct a link to log in as that user. I’d recommend doing that to test the system is working so far.
Actually hooking the login token into select links is very simple. Generate a new token in the mailer and add the token as a URL parameter in the template:
And that’s it. By scoping it down, it only took a few lines of code and will solve the problem for my most important emails (about four).