Jeff Kreeftmeijer

Authenticating via Github with Guestlist

2010-04-19

In last week’s article — “Simple authentication with Warden” — I explained that I wanted to allow users to log in with their Github credentials in a little application I’m working on.

The idea is that everyone with a Github account can simply log into the application by entering their username and token and we’ll automatically create an account with information fetched from the Github API. If the user already exists in our database, we won’t try to fetch anything. We already stored it.

I started working on it and realized that this may also come in handy for somebody else sometime, so I named it Guestlist and released it.

The installation is really simple, just throw this in your Gemfile:

gem 'guestlist'

And run:

$ bundle install

Or — if you’re using Rails 2.x — put this in config/environment.rb:

config.gem 'guestlist'

And run:

$ rake gems:install

Include Guestlist in your user model (mine is called User):

class User
  # It works with ActiveRecord too. ;)
  include MongoMapper::Document
  include Guestlist

  key :login,           String
  key :encrypted_token, String
end

Make sure you have both login and encrypted_token fields in your database if you’re using ActiveRecord (here’s a migration), or if you’re using MongoMapper, add some keys to your model like in the example above.

Believe it or not, you’re all set. Let’s try it (you can find your token on the Github account page):

User.authenticate 'github_login', 'github_token'

Guestlist will automatically create a new User for you and return that, or false if you’ve entered a wrong login or token. The user’s token is stored — yes, encrypted — , so next time you log in, it’ll just authenticate you via the database. If the token changes for some strange reason, Guestlist will update your user record when you log in with your new token.

Also, it works great with Warden. Here’s a strategy you can use:

def authenticate!
  u = User.authenticate(
    params[:login],
    params[:token]
  )
  u.nil? ? fail!("Couldn't log in") : success!(u)
end

Have fun and don’t forget to submit your issues or fork the project if you have a great idea.