Extending Devise SessionsController to authenticate using JSON

后端 未结 7 1296
面向向阳花
面向向阳花 2020-12-04 05:14

I am trying to build a rails API for an iphone app. Devise works fine for logins through the web interface but I need to be able to create and destroy sessions using REST AP

相关标签:
7条回答
  • 2020-12-04 05:48

    I ended up using a combination of @akshay's answer and @mm2001's answer.

    class Api::SessionsController < Devise::SessionsController
      def create
        warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#failure")
        render :json => {:success => true}
      end
    
      def destroy
        Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
        render :json => {}
      end
    
      def failure
        render :json => {:success => false, :errors => ["Login Failed"]}
      end
    end
    

    ... and in the devise initializer, I had to do this to get the #create method to use my :recall handler

    # config/initializers/devise.rb
    config.navigational_formats = [:"*/*", "*/*", :html, :json]
    

    This is with Devise 1.5.1 and Rails 3.1.

    0 讨论(0)
  • 2020-12-04 05:58

    An alternative solution to creating/destroying sessions is to use Devise's token_authenticatable module, and then update the other functions in your API so that they take the token as a mandatory parameter. This is arguably a more ReSTful design, since it retains statelessness (i.e., there's no session state anywhere). Of course, this advice holds for your JSON API, but I wouldn't recommend the same for your HTML UI (long token strings in your browser's URL bar are not a pretty sight).

    See here for an example.

    0 讨论(0)
  • 2020-12-04 05:59

    From the rdoc for devise's #devise_scope:

    Sets the devise scope to be used in the controller. If you have custom routes, you are required to call this method (also aliased as :as) in order to specify to which controller it is targetted.

    as :user do
      get "sign_in", :to => "devise/sessions#new"
    end
    

    Notice you cannot have two scopes mapping to the same URL. And remember, if you try to access a devise controller without specifying a scope, it will raise ActionNotFound error.

    It looks like you need to wrap it in a #as block:

    as :user do
      namespace :api do
        namespace :v1 do
          resources :sessions, :only => [:create, :destroy]
        end
      end
    end
    
    0 讨论(0)
  • 2020-12-04 06:02

    Not sure navigation-formats should be used, an API isn't really that...

    Per this blog post just add

    respond_to :html, :json
    

    to your controllers.

    0 讨论(0)
  • 2020-12-04 06:11

    A recent answer here: http://jessehowarth.com/devise has some more detail (per Using Devise 1.3 to authenticate JSON login requests)

    0 讨论(0)
  • 2020-12-04 06:11

    I solved the problem by creating a small service that dispenses authentication tokens. I wrote a blog post about it: http://matteomelani.wordpress.com/2011/10/17/authentication-for-mobile-devices/. You can also get the code here: https://github.com/matteomelani/Auth-Token-Service-Prototype.

    0 讨论(0)
提交回复
热议问题