I'm building mobile api based on Devise.
As long as I need json responses I have implemented custom SessionController and RegistrationController:
my routes.rb looks like:
devise_for(:users, :controllers => { :sessions => "api/sessions", :registrations => "api/registration"})
AFAIK, since last update auth_token in Devise is not used anymore (CHANGELOG.md under 3.1.0.rc).
Here is my registration controller:
class Api::RegistrationController < Devise::RegistrationsController
respond_to :json
skip_before_filter :verify_authenticity_token
def create
user = User.new(params[:user])
if user.save
render :json=> {:auth_token=>user.authentication_token, :email=>user.email}, :status=>201
#render :json=> {:success=>true}, :status=>201
return
else
warden.custom_failure!
render :json=> user.errors, :status=>422
end
end
protected
def invalid_login_attempt
render :json=> {:success=>false, :message=>"Error with your login or password"}, :status=>401
end
end
and session controller:
class Api::SessionsController < Devise::SessionsController
prepend_before_filter :require_no_authentication, :only => [:create ]
before_filter :ensure_params_exist
respond_to :json
skip_before_filter :verify_authenticity_token
def create
resource = User.find_for_database_authentication(:email => params[:email])
return invalid_login_attempt unless resource
if resource.valid_password?(params[:password])
sign_in("user", resource)
resource.ensure_authentication_token
render :json=> {:success=>true, :auth_token=>resource.authentication_token, :email=>resource.email}
return
end
invalid_login_attempt
end
def destroy
sign_out(resource_name)
end
protected
def ensure_params_exist
return unless params[:email].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
My user model:
class User < ActiveRecord::Base
before_save :ensure_authentication_token
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :email, :password, :password_confirmation, :remember_me
def ensure_authentication_token
if authentication_token.blank?
self.authentication_token = generate_authentication_token
end
end
private
def generate_authentication_token
loop do
token = Devise.friendly_token
break token unless User.where(authentication_token: token).first
end
end
end
As you can see from above, I've used this question to generate my own auth token. Unfortunately, after I authenticate with following query
curl -X POST -d '[email protected]&password=password' http://192.168.178.89:3000/users/sign_in
I obtain a token. But when I try to get protected data:
curl -X GET -d 'auth_token:UR-Hespxerzorw9UPK9Z' http://192.168.178.89:3000/api/orders.json
I get:
{"error":"You need to sign in or sign up before continuing."}
Can anyone point me to correct way of authentication? Thanks!
To do so, you can do the following steps:
1- Remove the before_filter :authenticate_user!
from the superclass of OrdersController
class, which should be ApplicationController
.
2- Create your own token check by adding the followings to your OrdersController
class:
before_filter :restrict_access
# Methods not shown
protected
def restrict_access
authenticate_or_request_with_http_token do |token, options|
User.exists?(authentication_token: token)
end
end
This looks for the authentication_token
you had created in the User
model and will match it with the request's token parameter.
3- To test the API, you can use the following curl
command:
curl -X GET -H 'Authorization: Token token="sdfksdf34heg5Ms"' http://192.168.178.89:3000/api/orders.json
where the token is what you got in response of the sign in request.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With