Duncan Malashock
Duncan Malashock

Reputation: 786

API routes for Devise Token Authentication

I'm using Devise in a Rails 3 app for user authentication. This app also serves API responses to a mobile application. I read that Devise removed their token authentication feature for various reasons, and I've implemented it in my application based on this gist: https://gist.github.com/josevalim/fb706b1e933ef01e4fb6

class ApplicationController < ActionController::Base
  protect_from_forgery

  # before_filter :authenticate_user_from_token!
  before_filter :authenticate_user! # Devise's default auth

  private

  def authenticate_user_from_token!
    user_email = params[:user_email].presence
    user       = user_email && User.find_by_email(user_email)

    if user && Devise.secure_compare(user.authentication_token, params[:user_token])
      sign_in user, store: false
    end
  end

end

Here's the first part of the controller in charge of API responses:

class ApiController < ApplicationController

  before_filter :cors_preflight_check
  after_filter :cors_set_access_control_headers

  before_filter :authenticate_user_from_token!

  # For all responses in this controller, return the CORS access control headers.

  def cors_set_access_control_headers
    headers['Access-Control-Allow-Origin'] = '*'
    headers['Access-Control-Allow-Methods'] = 'POST, GET, PUT, OPTIONS'
    headers['Access-Control-Max-Age'] = "1728000"
  end

  # If this is a preflight OPTIONS request, then short-circuit the
  # request, return only the necessary headers and return an empty
  # text/plain.

  def cors_preflight_check
    if request.method == :options
      headers['Access-Control-Allow-Origin'] = '*'
      headers['Access-Control-Allow-Methods'] = 'POST, GET, PUT, OPTIONS'
      headers['Access-Control-Allow-Headers'] = 'X-Requested-With, X-Prototype-Version'
      headers['Access-Control-Max-Age'] = '1728000'
      render :text => '', :content_type => 'text/plain'
    end
  end

  ... (response methods)

And my routes for the HTTP requests:

scope(:path => '/api/v1.0/') do
  match '/candidates' => "api#candidates"
  match '/districts' => "api#districts"
  match '/articles' => "api#articles"

  match '/candidates/:id' => "api#candidate"
  match '/districts/:id' => "api#district"
  match '/articles/:id' => "api#article"

  match '/search' => "api#search"
end

How do I create routes for logging in via API (the user submits a request with an email and password and receives a token)?

Upvotes: 1

Views: 1688

Answers (1)

S. A.
S. A.

Reputation: 3754

What do you mean with "How do I create routes"? Probably you want to create a class with a method to check email and password that returns the token, e.g.

class Tokens < ApplicationController

    def create

        @user = User.find_by_email(params[:email])
        # Check for password too!!

        if @user && @user.valid_password?(params[:password])
            render status: 200, json: { token: @user.authentication_token }
        else
          render status: 411, json: { error: "Error message..." }
        end
    end
end

And finally add to your routes:

post '/tokens' => "tokens#create"

Hope it helps.

Upvotes: 1

Related Questions