9

I'm trying to add Authentication via json in my project using devise configuration :token_authenticatable.

I have the working sessions_controller#create code which was taken from this article - http://blog.codebykat.com/2012/07/23/remote-api-authentication-with-rails-3-using-activeresource-and-devise/

def create
    build_resource
    resource = User.find_for_database_authentication(:email => params[:email])
    return invalid_login_attempt unless resource

    if resource.valid_password?(params[:password])
        resource.ensure_authentication_token!  #make sure the user has a token generated
        render :json => { :authentication_token => resource.authentication_token, :user_id => resource.id }, :status => :created
        return
    end
end

def invalid_login_attempt
    warden.custom_failure!
    render :json => { :errors => ["Invalid email or password."] },  :success => false, :status => :unauthorized
end

The problem is that native devise sessions_controller#create looks like this

  def create
    self.resource = warden.authenticate!(auth_options)
    set_flash_message(:notice, :signed_in) if is_navigational_format?
    sign_in(resource_name, resource)
    respond_with resource, :location => after_sign_in_path_for(resource)
  end

And i don't know how to combine this two create methods to have authentication working on website and via json too?

UPDATE

The working code

def create
    respond_to do |format|

      format.json do
        build_resource
        resource = User.find_for_database_authentication(:email => params[:email])
        return invalid_login_attempt unless resource

        if resource.valid_password?(params[:password])
          resource.ensure_authentication_token!  #make sure the user has a token generated
          render json: { authentication_token: resource.authentication_token, user_id: resource.id }, status: :created
          return
        end
      end

      format.html do
        self.resource = warden.authenticate!(auth_options)
        set_flash_message(:notice, :signed_in) if is_navigational_format?
        sign_in(resource_name, resource)
        respond_with resource, :location => after_sign_in_path_for(resource)
      end

    end
  end
2
  • I wrote up a blog post covering JSON API with Devise. Should help: jessewolgamott.com/blog/2012/01/19/… Commented Jan 14, 2013 at 17:40
  • @JesseWolgamott the OP asked for a solution that allowed both JSON and HTML-based authentication. Your post describes how to do the former but not the latter. Commented Jan 14, 2013 at 17:47

1 Answer 1

8

You want your SessionsController#create method to look something like this:

class Users::SessionsController < Devise::SessionsController
  def create
    resource = warden.authenticate!(scope: resource_name, recall: "#{controller_path}#new")
    set_flash_message(:notice, :signed_in) if is_navigational_format?
    sign_in(resource_name, resource)

    respond_to do |format|
      format.html do
        respond_with resource, location: redirect_location(resource_name, resource)
      end
      format.json do
        render json: { response: 'ok', auth_token: current_user.authentication_token }.to_json, status: :ok
      end
    end
  end
end 

...and make sure you've configured devise to use the token authentication key your clients will pass along.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.