public
Last active

API JSON authentication with Devise

  • Download Gist
registrations_controller.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
class Api::RegistrationsController < Api::BaseController
respond_to :json
def create
 
user = User.new(params[:user])
if user.save
render :json=> user.as_json(:auth_token=>user.authentication_token, :email=>user.email), :status=>201
return
else
warden.custom_failure!
render :json=> user.errors, :status=>422
end
end
end
sessions_controller.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
class Api::SessionsController < Api::BaseController
prepend_before_filter :require_no_authentication, :only => [:create ]
include Devise::Controllers::InternalHelpers
before_filter :ensure_params_exist
 
respond_to :json
def create
build_resource
resource = User.find_for_database_authentication(:login=>params[:user_login][:login])
return invalid_login_attempt unless resource
 
if resource.valid_password?(params[:user_login][:password])
sign_in("user", resource)
render :json=> {:success=>true, :auth_token=>resource.authentication_token, :login=>resource.login, :email=>resource.email}
return
end
invalid_login_attempt
end
def destroy
sign_out(resource_name)
end
 
protected
def ensure_params_exist
return unless params[:user_login].blank?
render :json=>{:success=>false, :message=>"missing user_login parameter"}, :status=>422
end
 
def invalid_login_attempt
warden.custom_failure!
render :json=> {:success=>false, :message=>"Error with your login or password"}, :status=>401
end
end

How do you have your routes set up for this controller?

@1ndivisible:

My routes for api are:

namespace :api do
  devise_for :users
  resources :recipes, :only=>[:index, :show]
end  

I also go into more detail http://jessewolgamott.com/blog/2012/01/19/the-one-with-a-json-api-login-using-devise/

Nice. Thanks a lot.

How are you authorizing your API controllers? You don't need to add the before_filter :authorize_users! in your API::BaseController

How are you authorizing your API controllers? You don't need to add the before_filter :authorize_users! in your API::BaseController?

@dellerbie I go into more detail here: http://jessewolgamott.com/blog/2012/01/19/the-one-with-a-json-api-login-using-devise/ .. but I do this to authorize a controller that requires authorization. The above would not, since they are the sign-in and sign-up controllers.


class Api::RecipesController < Api::BaseApiController
  before_filter :authenticate_user!
  #...
end

Nice, thanks for the response. Great blog post!

Does anyone have a small sample to demonstrate this. Let me look around I'll make one when I understand.

I forked this to work with latest devise: https://gist.github.com/2662058

InternalHelpers file is renamed, and made some other changes that now pass my tests

@jesse Okay I'll try it out.

On Fri, May 11, 2012 at 10:57 PM, Evan Beard <
reply@reply.github.com

wrote:

I forked this to work with latest devise: https://gist.github.com/2662058

InternalHelpers file is renamed, and made some other changes that now pass
my tests


Reply to this email directly or view it on GitHub:
https://gist.github.com/1255275

@jwo Have you got an example of routes.rb when using a :api namespace with a devise_for :users together with the normal devise_for :users?

Got the same problem as mentioned here: https://groups.google.com/group/plataformatec-devise/browse_thread/thread/d2f4776e5109c0b3?pli=1#

Wondering if you solved this or could point me in the right direction.

@drblok -- I wouldn't have 2 devise_for... You can have separate resources :users, but I don't see the need for multiple registration paths.

@drblok -- actually, sorry, that's incorrect... here's a setup for multiple devise paths. This works for me:

  devise_for :chefs, :path => '', :path_names => { :sign_in => "login", :sign_out => "logout", :sign_up => "register" }

  namespace "api/v1", :as=>:api do
    devise_for :chefs                                                                                                         
    resources :recipes, :only=>[:index, :show]
  end  

  resources :chefs, :only=>[:show,:edit, :update, :delete] do
    resource :avatar, :only=>[:show, :new, :create]
  end 

@jwo Thanks, I'll check it out and post my findings.

@jwo - I decided to remove the devise_for from my :api namespace and write my own as it's nothing more than rendering a JSON message if authentication fails. Thanks anyway for giving me stuff to think about to come to this conclusion ;)

Hi Matthew,

I've removed devise for my API namespace and wrote my own authentication which uses devise/warden to authenticate using an auth_token.

Hope this helps. If you need more info, just contact me :)

Regards,

Dennis

On Jun 20, 2012, at 5:37 AM, Matthew McClure wrote:

@drblok - I'm trying to do something very similar but the authentication token is not being returned in the JSON object. Does this not occur for you?


Reply to this email directly or view it on GitHub:
https://gist.github.com/1255275

Thanks for the response Dennis! I ended up using a lot of your registrations controller but I did remove the user.as_json in order to be able to return the token.

render :json=> user.as_json(:auth_token=>user.authentication_token, :email=>user.email), :status=>201

to

 render :json=> { :token=>user.authentication_token, :email=>user.email }, :status=>201

@sh1ps Errrr.. That's @jwo 's code, but glad it helps ;)

@drblok Errr...Well I feel like an idiot... I completely misread the flow of conversation. Thanks for offering up the help anyway!

Sorry to bring this back out from the dead, but doesn't before_filter :ensure_params_exist mean the app would also try to ensure parameters exist on destroy i.e. sign out ?

@hackfanatic yes. The line should be before_filter :ensure_params_exist, only: :create

I made some changes to the latest version of @Bomadeno.

What are the names of the helpers devise generates you? After adding namespaces i am forced to change my helpers.

namespace :api do
  namespace :v1 do
     devise_for :users
  end
end

Now i can access them like this current_api_v1_user or authenticate_api_v1_user!. Is there any way to maintain namespaces and access helper with just the name of the model?

thanks

I agree with @bilby91 that 2 namespaces are making the current_user quite ugly. What's the best practice to avoid this?

Hi there, I'm trying to make a API for a iOS app that will upload some videos to AWS s3. This is a great gist but, with the controllers are not extending from Devise::SessionsController and Devise::RegistrationsController?

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.