Devise API authentication

26,256

Solution 1

There is a devise configuration called :token_authenticatable. So if you add that to the devise method in your "user", then you can authenticate in your API just by calling

"/api/v1/recipes?qs=sweet&auth_token=[@user.auth_token]"

You'll probably want this in your user as well:

before_save :ensure_authentication_token

UPDATE (with API authorization code)

The method you're looking for are:

resource = User.find_for_database_authentication(:login=>params[:user_login][:login])
resource.valid_password?(params[:user_login][:password])

here's my gist with a full scale JSON/API login with devise

Solution 2

I would recommend reading through the Devise Wiki, as Devise natively supports token authentication as one of it's modules. I have not personally worked with token authentication in Devise, but Brandon Martin has an example token authentication example here.

Solution 3

Devise is based on Warden, an authentification middleware for Rack.

If you need to implement your own (alternative) way to authenticate a user, you should have a look at Warden in combination with the strategies that ship with Devise: https://github.com/plataformatec/devise/tree/master/lib/devise/strategies

Solution 4

If token auth just isn't what you want to do, you can also return a cookie and have the client include the cookie in the request header. It works very similar to the web sessions controller.

In an API sessions controller

class Api::V1::SessionsController < Devise::SessionsController

  skip_before_action :authenticate_user!
  skip_before_action :verify_authenticity_token

  def create
    warden.authenticate!(:scope => :user)
    render :json => current_user
  end

end

In Routes

namespace :api, :defaults => { :format => 'json' } do
  namespace :v1 do
    resource :account, :only => :show
    devise_scope :user do
      post :sessions, :to => 'sessions#create'
      delete :session, :to => 'sessions#destroy'
    end
  end
end

Then you can do this sort of thing (examples are using HTTPie)

http -f POST localhost:3000/api/v1/sessions user[email][email protected] user[password]=passw0rd

The response headers will have a session in the Set-Cookie header. Put the value of this in subsequent requests.

http localhost:3000/api/v1/restricted_things/1 'Cookie:_my_site_session=<sessionstring>; path=/; HttpOnly'
Share:
26,256

Related videos on Youtube

Xiaotian Guo
Author by

Xiaotian Guo

Updated on December 18, 2020

Comments

  • Xiaotian Guo
    Xiaotian Guo over 3 years

    I am working on a rails web application that also provides JSON based API for mobile devices . mobile clients are expected to first obtain a token with (email/pass), then clients will make subsequential API calls with the token.

    I am pretty new to Devise, and I am looking for a Devise API look like authenticate(email, pass) and expect it to return true/false, then based on that I will either create and hand back the token or return a decline message. but seems Devise doesn't provide something like this.

    I am aware that Devise 1.3 provides JSON based auth, but that's a bit different from what I need - I need to generate token and handle back to client, then after that auth is done using the token instead.

    Can someone please give some pointers?

    • Lucio
      Lucio over 8 years
      This is a great question, unfortunately the answers are outdated. We need new answers for Rails 4. I'm hoping to get it working soon :)
  • Xiaotian Guo
    Xiaotian Guo over 12 years
    thanks, however my problem is how to auth with email/pass to obtain the token, and that needs to happen using JSON, I cannot have users type a token on mobile devices.
  • Xiaotian Guo
    Xiaotian Guo over 12 years
    thank you Jesse, my problem isn't actually about the token itself, it's about how to do a custom email/pass auth in JSON from mobile device, to obtain the token.
  • Jesse Wolgamott
    Jesse Wolgamott over 12 years
    Updated with the method and gist you're looking for.
  • Xiaotian Guo
    Xiaotian Guo over 12 years
    Thank you again Jesse, exactly what I was looking for
  • Abhay Kumar
    Abhay Kumar almost 12 years
    I get valid_password? undefined method error. I assume that valid_password is a method in Devise and i need not implement it
  • Jesse Wolgamott
    Jesse Wolgamott almost 12 years
    @AbhayKumar depends on the devise options. you might need database_authenticable --- please open a new question.
  • okliv
    okliv almost 11 years
    example link is broken
  • lightswitch05
    lightswitch05 over 10 years
    An update to people looking at this, :token_authenticatable is now deprecated.
  • Carles Jove i Buxeda
    Carles Jove i Buxeda over 9 years
    If you get here after November 2013, you need to know that Authenticable has been removed from Devise, so this solution won't probably work. Check this out: github.com/plataformatec/devise/wiki/…