Skip to content

Instantly share code, notes, and snippets.

@jwo
Created September 30, 2011 23:11
Show Gist options
  • Select an option

  • Save jwo/1255275 to your computer and use it in GitHub Desktop.

Select an option

Save jwo/1255275 to your computer and use it in GitHub Desktop.
API JSON authentication with Devise
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
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
@mmcc

mmcc commented Jun 20, 2012

Copy link
Copy Markdown

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

@drblok

drblok commented Jun 20, 2012

Copy link
Copy Markdown

np!

@meshaabi

Copy link
Copy Markdown

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 ?

@dieb

dieb commented Mar 8, 2013

Copy link
Copy Markdown

@natebird

Copy link
Copy Markdown

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

@johnjohndoe

Copy link
Copy Markdown

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

@bilby91

bilby91 commented Aug 30, 2013

Copy link
Copy Markdown

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

@onetom

onetom commented Sep 26, 2013

Copy link
Copy Markdown

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

@ricbermo

Copy link
Copy Markdown

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?

@minhtriet

Copy link
Copy Markdown

Try another method, taken from my Spree Application

    user = Spree::User.find_by(:email => params[:email])
    unless user.nil?
      if user.valid_password? params[:password]
        render :json => '{"api_key": "#{user.spree_api_key}"}'
      end
    end
    render :json => '{"error": "invalid email and password combination"}'

The point is that you can use valid_password? in devise for your convenient

@netwire88

Copy link
Copy Markdown

Thanks minhtriet, this is useful and simpler. Do you have the RegistrationsController gist?

@DanielWright

Copy link
Copy Markdown

Is there a reason not to use warden.authenticate instead of reinventing the wheel with your own finder and password-validation logic?

@codemilan

Copy link
Copy Markdown

getting error
"undefined local variable or method `build_resource' for #Api::SessionsController:0x00000003f885b0"
i'm using devise 3.4.1 in rails 4.1.5, I have removed line 'include Devise::Controllers::InternalHelpers' and extended 'Api::SessionsController' < DeviseController, also I have not included the related file Api::RegistrationsController in my api does it affect ?
so what's the exact cause please clarify.

ghost commented Nov 29, 2014

Copy link
Copy Markdown

@thandang

Copy link
Copy Markdown

Dear,

It's nice post.
But I have one question.
How about if I setting for Devise with maximum_attempts = 5 and lock_strategy = :failed_attempts
Does it work like normal web base.
Currently I'm using device for connect to API,

It's really helpful to get answers.
Thanks a lot.

@mices

mices commented Feb 23, 2017

Copy link
Copy Markdown

I get this error in rails
TypeError in Devise::ConfirmationsController#show
nil is not a symbol nor a string
Extracted source (around line #188):

186
187
188
189
190
191

# Handles <tt>*_was</tt> for +method_missing+.
def attribute_was(attr) # :nodoc:
  attribute_changed?(attr) ? changed_attributes[attr] : __send__(attr)
end

# Handles <tt>*_previously_changed?</tt> for +method_missing+.

@jgonzalezd

jgonzalezd commented May 9, 2017

Copy link
Copy Markdown

@onetom:

namespace :api do
    namespace :v1 do
      devise_for :users, defaults: { format: :json }, as: :users
   end
end

 new_users_user_session GET    /api/v1/users/sign_in(.:format)  api/v1/sessions#new {:format=>:json}
 users_user_session POST   /api/v1/users/sign_in(.:format)  api/v1/sessions#create {:format=>:json}

@NSLog0

NSLog0 commented Jul 20, 2017

Copy link
Copy Markdown

Good example but confused about where you set token?

ghost commented Sep 24, 2017

Copy link
Copy Markdown

In this way failed_attempts, doesn't work.

@xhocquet

Copy link
Copy Markdown

@Avatarr in this instance, the tokens are probably set or generated by Devise. This was removed from Devise after 3 for security reasons, though you can use a basic implementation like this one to get the functionality back

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment