web-dev-qa-db-ja.com

Rails apiおよびネイティブモバイルアプリ認証

このトピックについて多くの情報があることは知っていますが、最新の情報は見つかりません。 RailsおよびAndroid authentication に関連するこのトピック)のようなトピックが表示されますが、- TokenAuthenticatableはdevise から削除されました。

私の質問は単純です。ネイティブAndroidおよびRails 4を使用するiPhoneアプリ)からユーザーを認証する良い方法はありますか?ソリューションを提供しますか?

Adam Waiteバウンティの追加:

IOSアプリからRails APIへのユーザー認証の正しい方法を見つけることができないため、この質問で500バウンティを開きました。これは私が検討していたことですが、安全かどうかわかりません!:

Userレコードがあるとします。ユーザーが、User列とpassword_digest列を持つemailレコードをデータベースに作成したアカウントにサインアップしました。

ユーザーがサインインするとき、明示的にサインアウトするまで、そのユーザーをモバイルアプリで認証されたままにします。

トークンベースの認証が必要になると思います。 Userの作成時にApiKeyレコードを作成し、Userレコードの関連付けとして保存することができます。

ユーザーがサインインまたはサインアップすると、応答にはAPIトークン(SecureRandom.hexなど)が含まれます。これはiOSキーチェーンに保存され、後続のすべてのリクエストで使用され、ヘッダーで渡してユーザーを確認します。それは次のようなものを使用します:

before_filter :restrict_access

private

def restrict_access
authenticate_or_request_with_http_token do |token, options|
  ApiKey.exists?(access_token: token)
end

これは安全ですか?すべてのリクエストでトークンを更新し、それをレスポンスに含める必要がありますか?

他にどのようなオプションがありますか? Facebook、Twitter、Pinterestなどは何をしますか?

OAuth2.0は知っていますが、外部アプリケーションを許可するためのものではありませんか?

これを管理する宝石はありますか?

申し訳ありませんが、ここでは完全に不明です。

最高の答えに500。

31
agonist_

私の研究からの解決策の要点。自由に編集、修正、無効化などしてください。

SessionsController < ApplicationController
  skip_before_filter :authenticate_user, :only => [:create]
  def create
    user = User.where("username = ? OR email = ?", params[:username_or_email], params[:username_or_email]).first
    if user && user.authenticate(params[:password])
      api_key = user.find_api_key
      if !api_key.secret_key || api_key.is_expired?
        api_key.set_expiry_date
        api_key.generate_secret_key
      end
      api_key.save
      render json: api_key, status: 201     
    else
      status: 401
    end
  end

ApiAuth.authenticに注意してください。メソッドとリクエストオブジェクト。リクエストは、クライアントのHMACアルゴリズムで署名されている必要があります。

ApplicationController < ActionController::Base
  respond_to :json
  force_ssl
  protect_from_forgery with: :null_session 
  before_filter :authenticate_user
  private
  def authenticate_user
    if authenticate_user_from_secret_key
      return true
    else
      head :unauthorized 
    end
  end
  def authenticate_user_from_secret_key
    userid = ApiAuth.access_id(request)
    currentuser = userid && User.find_by_id(userid)
    if ApiAuth.authentic?(request, currentuser.find_api_key.secret_key)
      return true
    else
      return false
    end
    false
  end

ユーザーの作成/登録

UsersController < ApplicationController
  skip_before_filter :authenticate_user, :only => [:create]
  def create
      user = User.create(user_params)
      if !user.new_record?
        render json: user.find_apit_key, status: 201

      else
       # error
      end
  end

APIキーモデル。 #352 railscastのAPIキーモデルと同様に、ApiAuthキーの生成のみが異なります。

class ApiKey < ActiveRecord::Base
  before_create :generate_secret_key, :set_expiry_date
  belongs_to :user   
  def generate_secret_key
    begin
    self.secret_key = ApiAuth.generate_secret_key
    end while self.class.exists?(secret_key: secret_key)
  end

ユーザーモデル。

class User < ActiveRecord::Base
  has_secure_password
  before_save :ensure_api_key 
  has_many :api_keys 
  def find_api_key
   self.api_keys.active.ios.first_or_create
  end

クライアント側では、HMACアルゴリズムを使用してリクエストに署名する必要があります。

コードは次のとおりです。[SHA1 HMACキーの生成/認証] https://github.com/mgomes/api_auth [Controllers&Models] https://github.com/danahartweg/ authenticatable_rest_api

13

私はこの問題を抱えていました。私はAPI開発者です。あなたはできますトークンとカスタム認証で難しい方法を実行しますが、6桁のユーザーにサービスを提供するアプリケーションで何をするかを説明します図。

少なくともiOSの場合、デバイスはセッションを処理します。つまり、iOSアプリのユーザーがPOSTに/users/sign_inパラメータ付き

user: { 
  password: 'mypassword',
  email: '[email protected]',
  remember_me: true # optional
}

iOSデバイスは、セッションを安全かつ永続的に保存します。

ここで、OAuth 2ルートに移動したい場合、実際にはRails 4と呼ばれるOAuth 2提供可能です。ユーザーに「認証」画面を通過させるためのかなりクールな機能を追加しました。ソフトウェアを開発した場合、ユーザーがユーザーを信頼していることを確認する必要がないことは明らかです。

OAuth 2を使用する場合は、暗黙のアクセストークンと呼ばれるものを使用する必要があります。 これは長く、非常にそのための退屈なOAuth2仕様

Rails 4プロジェクトはgithubにあります https://github.com/bwheeler96/devise-oauth2-provider-Rails4

Rails 4でない場合は、元のgemを使用できます https://github.com/socialcast/devise_oauth2_providable

ちなみにgemには作業が必要なので、これを読んでもっと良くしたい人がいたら、ぜひフォークしてください this repository

5
OneChillDude

順調ですが、ユーザーのトークンは、どのユーザーがリクエストを行っているかを識別するためにのみ使用する必要があります。要求ごとにトークンを変更することで推測すると、ハッカーはデータストリームを傍受し、トークンを取得して、その後の要求でそのユーザーを "利用"できるため、依然として何らかの認証が必要です。

リクエストごとにトークンを変更することで、インターセプトの問題を排除できますが、誰かがトークンをインターセプトすると、トークンをインターセプトし続け、レスポンスを変更することで、システムをさらに悪用することができます。これに対する1つの解決策は、HMAC(Amazon Webサービスで使用される)を使用することです。これは、すべてのリクエストに対して一意であり、変更キーを必要とせず、将来のリクエストに対して予測できない、リクエストに署名(ハッシュ)を提供するアルゴリズムです。

Ruby gem for Railsこれはサーバー間でHMACを実装し、サーバー間通信を行うときにHMAC要求に署名するためにそれらを生成する)があります。あなたの場合のようにクライアントからサーバーへのリクエストの場合、iOSまたはAndroid側で署名を生成し、サーバーでそれらを認証する必要があります。

ApiAuth gemをサーバー側で処理することを検討してください。 iOSクライアント側では、署名を生成するために [〜#〜] hbhmac [〜#〜] ライブラリを検討してください。 ApiAuthの特定の実装を確認してください。リプレイ攻撃を防ぐためにデータにタイムスタンプが追加されるため、HBHMACに渡す前にデータにフィールドを追加する必要がある場合があります。

要約すると、HMAC認証を使用すると、攻撃者が有効な要求を傍受できたとしても、攻撃者が本物の要求を生成できない一方向ハッシュアルゴリズムを利用して、中間者攻撃とリプレイ攻撃を回避できます。

5
Troy

OAuth2.0をRuby on Railsで使用する場合は、Doorkeeperを使用することになります。ここに例(無料ではありません)を示します。

http://railscasts.com/episodes/353-oauth-with-doorkeeper

ただし、SecureRandom.hexでトークンを使用できます。これの例(無料ではありません)は次のとおりです(レベル6)。

https://www.codeschool.com/courses/surviving-apis-with-Rails

私の答えがあなたを助けることを願っています!

2
Ciro Mine