Authentication API for Ruby on Rails (Devise)

Devise is a commonly used authentication gem for Rails projects. It comes with controllers, data model and html templates that don’t require much time for configuration. Basically it works just out of the box for web projects. However, to my surprise, Devise is not that friendly with non-web clients. Say, you’ve built a REST API that works with your web app and now you want to reuse it with mobile native apps. Sounds reasonable and easy to do at first glance, isn’t it? Well, it’s not that easy with Devise.
If you try to google solutions for this matter, most likely you’ll stumble upon articles, talking about token authentication approach, similar to this one:
http://matteomelani.wordpress.com/2011/10/17/authentication-for-mobile-devices/
Unfortunately, this solution does not work anymore, because Devise changed.
It’s still possible to use token authentication, but you have to modify the code of your Session controller and Devise itself. I found that using token is not necessary as authentication cookies were working too. I did not need to change the Devise and append every single URL with ?auth_token=.
In one of the Devise own examples called “Simple Token Authentication” you can find following message:

Note: these examples are out of date, TokenAuthenticatable has been removed from Devise. See this gist for alternatives.

Here’s the gist it’s referencing to:
https://gist.github.com/josevalim/fb706b1e933ef01e4fb6

New article on how to build an API with Devise authentication:
http://www.soryy.com/ruby/api/rails/authentication/2014/03/16/apis-with-devise.html

Good article with the example that returns authentication token and result of the authentication back to the client:
http://jessewolgamott.com/blog/2012/01/19/the-one-with-a-json-api-login-using-devise

Basically, in order to make token authentication work again, you need to merge modifications for ApplicationController from gist I mentioned above and SessionController the way it’s shown in the last article.

My SessionController looks like this:

class SessionsController < Devise::SessionsController
  skip_before_filter :verify_authenticity_token

  def create
    respond_to do |format|
      format.html do
        params[:user].merge!(remember_me: 1)
        super
      end
      format.json do
        resource = User.find_for_database_authentication(:email => params[:email])
        return invalid_login_attempt unless resource
        resource.ensure_authentication_token

        if resource.valid_password?(params[:password])
          sign_in(:user, resource)
          render :json => {:success => true, :auth_token => resource.authentication_token, :email => resource.email}
        else
          invalid_login_attempt
        end
      end
    end
  end

  def invalid_login_attempt
    render :json => {:success => false, :error => "invalid login"}
  end

end

Leave a Reply

Proudly powered by WordPress
Theme: Esquire by Matthew Buchanan.