Tuesday, 22 March 2011

Ruby on Rails 3 - Installing Devise authentication on Heroku

A few days ago I decided to add authentication to my Rails 3 app. I came across a few alternatives but in the end opted for Devise as this seems to be the newest and from the documents I found apparently the easiest to implement.
I needed users to be able to register new users, sign in and out and to have special admin users who could access restricted areas of the site, Devise hit all these requirements.

So I found a couple of good tutorials including https://github.com/plataformatec/devise and associated wiki https://github.com/plataformatec/devise/wiki/_pages and found these really good at getting me up and going quickly.

I got everything working locally but then when I pushed my git repo to Heroku I got the error when using the register page: We're sorry, but something went wrong. We've been notified about this issue and we'll take a look at it shortly.

so to the command line 'Heroku logs' revealed this error:
2011-03-21T14:03:09-07:00 app[web.1]: NameError (uninitialized constant Devise::Encryptors::Bcrypt):

It took me a while but after searching around any trying all sorts of things i hit the answer. and as usual it was simple, if you are deploying to heroku you need to add bcrypt-ruby to your gemfile like so:

gem 'devise', '1.1.8'
gem 'bcrypt-ruby', '2.1.4'

Also remember to generate and commit your new gemfile.lock into git and send this to heroku as well as the new gemfile or you will get the following error, as i did:

You have modified your Gemfile in development but did not check
the resulting snapshot (Gemfile.lock) into version control
You have added to the Gemfile:
* bcrypt-ruby (= 2.1.4)
FAILED: http://docs.heroku.com/bundler
Heroku push rejected, failed to install gems via Bundler

My Devise Authentication Implementation
I've added the following to the top of all my admin controller classes to ensure that only administrators can access them

before_filter :authenticate_user!
before_filter :authorise_user!

The method :authenticate_user! is a helper method built into Devise
The method :authorise_user! is my own declared in ApplicationController as follows:

def authorise_user!
  if ! current_user.try(:admin?)
    flash[:alert] = "Unauthorised"
    redirect_to ''

where admin is a boolean field on the devise created user table. (I used option 2 from this wiki page)

For controllers which none admin users have access to I want to restrict them so that they can only see resources that they created. So for example, bob created an order-x, you don't want James to be able to access that order-x it belongs to bob not James.

For this I've created methods similar to:

def authorise_as_owner!
  order = Order.find(params[:id])
  unless current_user.try(:admin?) || order.user_id == current_user.id
    flash[:alert]  = "Not your order!"
    redirect_to ''

No comments:

Post a Comment