-
-
Save marcomd/3129118 to your computer and use it in GitHub Desktop.
#Session controller provides a token | |
#/controllers/api/sessions_controller.rb | |
class Api::SessionsController < Devise::SessionsController | |
before_filter :authenticate_user!, :except => [:create] | |
before_filter :ensure_params_exist, :except => [:destroy] | |
respond_to :json | |
def create | |
resource = User.find_for_database_authentication(:email => params[:user_login][:email]) | |
return invalid_login_attempt unless resource | |
if resource.valid_password?(params[:user_login][:password]) | |
sign_in(:user, resource) | |
resource.ensure_authentication_token! | |
render :json=> {:auth_token=>resource.authentication_token, :email=>resource.email}, :status => :ok | |
return | |
end | |
invalid_login_attempt | |
end | |
def destroy | |
resource = User.find_by_authentication_token(params[:auth_token]||request.headers["X-AUTH-TOKEN"]) | |
resource.authentication_token = nil | |
resource.save | |
sign_out(resource_name) | |
render :json => {}.to_json, :status => :ok | |
end | |
protected | |
def ensure_params_exist | |
return unless params[:user_login].blank? | |
render :json=>{:message=>"missing user_login parameter"}, :status=>422 | |
end | |
def invalid_login_attempt | |
render :json=> {:message=>"Error with your login or password"}, :status=>401 | |
end | |
end | |
#Base controller which inherited by every api controller | |
#/controllers/api/base_controller.rb | |
class Api::BaseController < InheritedResources::Base | |
before_filter :authenticate_user! | |
prepend_before_filter :get_auth_token | |
respond_to :xml, :json | |
private | |
def get_auth_token | |
if auth_token = params[:auth_token].blank? && request.headers["X-AUTH-TOKEN"] | |
params[:auth_token] = auth_token | |
end | |
end | |
end | |
#Your resources controllers | |
#/controllers/api/v1/products_controller.rb | |
module Api | |
module V1 | |
class ProductsController < Api::BaseController | |
end | |
end | |
end | |
#Routes | |
namespace :api, :defaults => {:format => 'json'} do | |
devise_for :users | |
namespace :v1 do | |
resources :products | |
end | |
end | |
#*** How to get a token: well, you have to provide email and password *** | |
#with curl | |
curl -d "user_login[email][email protected]&user_login[password]=yourpassword" http://localhost:3001/api/users/sign_in --noproxy localhost | |
{"email":"[email protected]","success":true,"auth_token":"G3xbSrS4uqLU484eUw9h"} | |
#with HTTPClient | |
clnt = HTTPClient.new | |
res = clnt.post("http://localhost:3001/api/users/sign_in", {"user_login[email]" => "[email protected]", "user_login[password]" => "yourpassword"}) | |
auth_token = JSON(res.body)["auth_token"] | |
=> "G3xbSrS4uqLU484eUw9h" | |
#*** How to get data using the token *** | |
#with curl | |
curl -H "X-AUTH-TOKEN: G3xbSrS4uqLU484eUw9h" http://localhost:3001/api/v1/products/1 --noproxy localhost --get | |
#with HTTPClient gem | |
clnt = HTTPClient.new | |
clnt.get("http://localhost:3001/api/v1/products/1", nil, {"X-AUTH-TOKEN" => "G3xbSrS4uqLU484eUw9h"}).content | |
#*** At the end, remove the access token *** | |
#with curl | |
curl -X DELETE -H "X-AUTH-TOKEN: G3xbSrS4uqLU484eUw9h" http://localhost:3001/api/users/sign_out | |
#with HTTPClient gem | |
clnt.delete("http://localhost:3001/api/users/sign_out", {"X-AUTH-TOKEN" => "G3xbSrS4uqLU484eUw9h"}) | |
thanks man
Np :)
I just added routes.
If you have operations extra rest, for example close:
namespace :api, :defaults => {:format => 'json'} do
devise_for :users
namespace :v1 do
resources :products do
member do
get 'close'
end
end
end
end
then, in your client application, you can use it with active resource model (first comment) in this manner
Product.find(1).get :close
I was looking for having auth token through header. I seems prepend_before_filter did the trick.
Great gist!
Does this approach leave open the possibility of CSRF?
If you use before_filter :authenticate_user!, it will check to see if user is logged in by any possible mean (not only auth_token), and if CSRF token is not checked, another website can get your data, right?
Thank you! I is very helpful :)
Any idea why I would be getting "NoMethodError (undefined method 'ensure_authentication_token!' for #User:0x007f3764a07470>):"? Where should this be defined?
With an API REST like this you can map external resource in another rails app.