web-dev-qa-db-ja.com

Rails AP​​I:認証を実装する最良の方法は?

まだ開発されていないモバイルアプリのAPIを公開するRails 4アプリを作成しています。ユーザーは、モバイルアプリの電子メールとパスワードを使用して認証します。

トピックに関する多くの情報を見つけましたが。日付のあるものや最適でないものを見分けるのは困難です。私はあまり安全ではないと思われるHTTP基本認証とHTTPトークンベースの認証について読みましたが、それを通常の電子メールとパスワード認証と組み合わせる方法についてはわかりません(私はDeviseを使用しています道)。

これを実装する方法に関する現在のベストプラクティスを知りたいので、正しい方法で作業することを確認します。

75
Roma149

セキュリティの観点からの重要なポイントは、ユーザーの電子メールとパスワードを一度トークンと交換し、その後そのトークンを以降のリクエストに使用することです。それの訳は:

  1. クライアントアプリがユーザーのパスワードを保持する責任を負わないようにします。バグや攻撃によりパスワードが漏洩する可能性があります。そして
  2. サーバーが発行したトークンを使用すると、必要に応じてトークンを期限切れにすることができます。盗まれたデバイスをロックアウトするか、不正なAPIクライアントをブロックします。

これを達成するには、さまざまなレベルの複雑さで多くの方法があります。

これは非常に最近のチュートリアルで、Railsでトークンベースの認証を使用してAPIを作成するための詳細なチュートリアルがあります(Deviseを使用しませんが、概念の理解に関連しています): https: //labs.kollegorna.se/blog/2015/04/build-an-api-now/

48
Matt Brictson

別のオプションは、以下のモジュールをデバイスモデルに含め、auth_tokenをテーブルに追加することです。

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
...

編集:修正されたコード違反のタイプミス

5
Antarr Byrd

@ Roma149これは個人的な好みですが、最も簡単なIMOであるDeviseを使用し始めたばかりの人がほとんどです。 OAuth2も適切なオプションです。より重要な注意事項として、常に The Ruby Toolbox にアクセスできます

そこには宝石に関する多くの良い情報があり、宝石の年齢や人気も教えてくれます。これにより、コミュニティが実際に探しているジェムと陳腐化したジェムを区別することもできます。

RubyおよびRubyのRailsで覚えておくと、常に優れたgemであるとは限りませんが、プロジェクトに最適なものです!

4
The Gugaru

Tiddlegemは、APIのみのRuby on Railsアプリケーションでトークン認証のDevise戦略を提供します。その主な機能は、ユーザーごとの複数トークンのサポートです。

https://github.com/adamniedzielski/tiddle

3
Zakaria