简体   繁体   中英

Rails: Unable to sign_in a user using Devise

I created a demo authentication application in rails using Devise gem. I created a sessions controller to sign in a user. But when I'm sending a request localhost:3000/api/v1/sessions/ using postman to the session controller I'm getting the following error :

"Could not find a valid mapping for #<User id: 2, email: "smith@railsapi.com", encrypted_password: "$2a$10$J5lCfQzWsxvjsXe.3EXfZ.ST9nztLLW8fhqYgXNtJP1...", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, created_at: "2016-03-26 03:59:22", updated_at: "2016-03-26 03:59:22", auth_token: "_D3GU1TftgP7YHNcRftN">"

Here's my model users.rb

class User < ActiveRecord::Base



 before_create :generate_authentication_token!

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
  validates :auth_token, uniqueness: true

  def generate_authentication_token!
    begin
      self.auth_token = Devise.friendly_token
    end while self.class.exists?(auth_token: auth_token)
  end
end

Here's my sessions controller

class Api::V1::SessionsController < ApplicationController

  def create
    user_password = params[:session][:password]
    user_email = params[:session][:email]
    puts user_password
    puts user_email
    user = user_email.present? && User.find_by(email: user_email)

    if user.valid_password? user_password
      sign_in user, store: false
      user.generate_authentication_token!
      user.save
      render json: user, status: 200
    else
      render json: { errors: "Invalid email or password" }, status: 422
    end
  end
end

And My routes.rb file :

Rails.application.routes.draw do
  # API routes path
  namespace :api, defaults: { format: :json } do
    namespace :v1 do
      resources :users, only: [:show, :create, :update]
      resources :sessions, only:[:create, :destroy]
    end
  end  
end 

Application.rb

require File.expand_path('../boot', __FILE__)

require 'rails/all'

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module DemoApi
  class Application < Rails::Application
    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration should go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded.

    # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
    # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
    # config.time_zone = 'Central Time (US & Canada)'

    # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
    # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
    # config.i18n.default_locale = :de

    # Do not swallow errors in after_commit/after_rollback callbacks.
    config.active_record.raise_in_transactional_callbacks = true

    DeviseController.respond_to :html, :json
  end
end

I would really appreciate if someone can tell me where I'm going wrong. Thanks

A better and easy way to solve this problem is using devise with devise_token_auth gem to accomplish the JWT(JSON Web Token) authentication system. This gem will give you all the tools you need to create a JWS system. We had a talk about API Authentication in my town and I created a basic app using this feature. I will describe how I have implemented the solution here, but fell free to check it out the Sample Repo here . It is an Instagram-like app.

Step 1: Add to your Gemfile:

gem 'devise_token_auth'

Install the gem

$ bundle install

step 2 : generate the configurations needed by the gem

$ rails generate devise_token_auth:install User auth
$ bundle exec rake db:migrate

It will generate a migration file that adds a couple of new attributes to your user model, but basically the main line is that:

 ## Tokens
  t.text :tokens

It will provide an array of tokens that will be kept in the database for user authentication

It also adds the routes for authentication/sign_in/sign_up

mount_devise_token_auth_for "User", at: 'auth'

step 3: lookup for the routes

Now, on your terminal, execute:

$ rake routes

It will show the routes for authentication , sign in and sign_up

step 4: Using postman to try it out

As you mentioned, using the Postman, you now can send a POST to localhost:3000/auth/ with email , password , and password_confirmation (those fields are required) to register the user. (Check the devise_token_auth README to see how to sign_in and sign_out ).

The key here is that registration request and sign_in request will return the response with many headers(if the status code was OK) that contains all the authentication information you need. You have to extract those headers on your mobile client(or even using postman to test the authentication required routes) and add to all further requests that require authentication in your app.

Try to do that, clone and check the Sample Repo that I pointed out and see if you get it done. Let me know if you got it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM