Rails API : Best way to implement authentication?

前端 未结 4 1907
清酒与你
清酒与你 2020-12-12 17:35

I\'m writing a Rails 4 app that will expose an API for a mobile app that\'s yet to be developed. Users will authenticate using an e-mail and password from the mobile app.

相关标签:
4条回答
  • 2020-12-12 18:32

    @Roma149 this is more of a personal preference but most people who are just starting out use Devise as it is the easiest IMO. OAuth2 is a good option as well. As a more important note you can always go to The Ruby Toolbox

    There is a lot of good information on gems there and they even tell you the age and the popularity of the gem. This will also allow you to differentiate between what gems the community is really geeking out on now or what has gone stale.

    Remember in Ruby and Ruby On Rails it is not always what is better gem wise but what best fits your project!

    0 讨论(0)
  • 2020-12-12 18:34

    Another option is to include the module below in your devise MODEL and add the auth_token to you table.

    app/models/concerns/token_authenticable.rb

    module TokenAuthenticatable
      extend ActiveSupport::Concern
    
      included do
        before_save :ensure_auth_token
      end
    
      module ClassMethods
        def find_by_token(token)
          find_by(auth_token: token)
        end
      end
    
      def ensure_auth_token
        self.auth_token = generate_auth_token if auth_token.blank?
      end
    
      private
    
      def generate_auth_token
        loop do
          token = Devise.friendly_token
          break token unless self.class.exists?(auth_token: token)
        end
      end
    end
    

    app/controllers/api/v1/login_controller.rb

    ...
     def login_user(params)
        if params[:authentication]
          @user = User.find_by(auth_token: params[:authentication])
          if @user.nil?
            render json: err('login user by token failed', ERR_USER_NOT_FOUND), status: :not_found
            event('login_user_by_auth_failed', 'token', params[:authentication])
            return
          else
            render status: :ok, json: @user
            return
          end
        else
          user = user.find_by(email: params[:email])
          if user.nil?
            event('login_user_failed_not_found', 'user_email', params[:email])
            render json: err("login user not found #{params[:email]}", ERR_USER_NOT_FOUND), status: :not_found
            return
          end
          if user.access_locked?
            event('login_user_blocked', 'user_id', user.id)
            render json: err("login user account is locked : #{user.id}", ERR_USER_LOCKED), status: :unauthorized
            return
          end
          unless user.try(:valid_password?, params[:password])
            event("login_user_password_does_not_match #{user.id}", 'user_id',  user.id)
            render json: err('login user password does not match', ERR_PASSWORD_NOT_MATCH), status: :unauthorized
            return
          end
          event('login_user_succeeded', 'user_id', user.id)
          @user= user
          if @user.save
            response.headers['authentication'] = @user.auth_token
            render status: :ok, json: @user
            return
          else
            render json: @user.errors, status: :unprocessable_entity
            return
          end
        end
      end
    ...
    

    Edit: Corrected code-breaking typo

    0 讨论(0)
  • 2020-12-12 18:35

    Tiddle gem provides Devise strategy for token authentication in API-only Ruby on Rails applications. Its main feature is support for multiple tokens per user.

    https://github.com/adamniedzielski/tiddle

    0 讨论(0)
  • 2020-12-12 18:39

    The important point, from a security perspective, is to exchange the user's email and password for a token once, and then use that token for subsequent requests. This is because:

    1. You don't want the client app to be responsible for holding onto the user's password, where a bug or attack could cause it to be leaked; and
    2. A server-issued token gives you (and your users) the ability to expire a token if necessary, e.g. to lock out a stolen device or block a misbehaving API client.

    There are many ways to accomplish this with varying levels of complexity.

    Here is a tutorial that is very recent and has a thorough walkthrough for creating an API in Rails with token-based authentication (not using Devise, but still relevant to understand the concepts): https://labs.kollegorna.se/blog/2015/04/build-an-api-now/

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