2011-08-29 21 views
7

Facebookの認証を使用してログインできるように、devise & omniauthを使用するレールアプリの設定があります。現在、HTTP認証を使用してモバイルアプリを使用しており、ユーザー名&を渡すか、http認証トークンを渡すことで、レールアプリにログインします。これはすべてこれまで素晴らしいです。認証トークンとしてオプションのomniauthトークンを使用して、deviseでhttp認証を使用する方法

モバイルアプリは、facebook自体で認証し、facebookトークンを自分とfacebookとの間で直接受け取ることもできます。

私はこのギャップを埋めるために、ユーザーがFacebookからモバイルアプリからログインしてfacebookトークンを持っていれば、そのfacebookトークンを受信したかのようにそれはブラウザを介してFacebookから。

最終結果は、モバイルアプリ経由でユーザをログインすることができるであろう。

1)ユーザ名/パスワード 又は 2)HTTP

トークン認証トークン 又は 3)omniauth(Facebookの)

また、3)の場合、ユーザーがまだレールアプリに存在しない場合は、ユーザーを作成する必要があります。ブラウザ側の認証でこれを行う必要があります。

私はdevise構造内でどのようにこれを達成するのが最適でしょうか?

答えて

10

これをやっただけで、エンドツーエンドのソリューションは見られませんでした。

このアドレスのポイント3. 1 & 2は、他の場所で考案され、文書化されています。

あなたのウェブアプリにFB認証を追加するのは難しくありませんが、指示はomniauthとomniauth-facebookのgithubにあります。

オムニバスとフェイスブックの統合をしないと、次のようなことが起こります。これはそこにある他のアプローチに似ています。私の考えは、私ができる限り機密モデルを使用するように試みることでした。

あなたはfb_graph宝石が必要です。

モバイルクライアントでは、FBで適切に認証し、返されたアクセストークンをHTTPリクエストのヘッダーに入れます。私はヘッダfb_access_tokenを使用しました。 基本認証と同じように、トークンのスニッフィングを避けるためにSSL経由で送信することをお勧めします。ヘッダーを使用すると、要求を変更せずに基本認証とFB認証を交換できますが、必要に応じてパラメータを使用できます。

このソリューションは、脆弱性の認証可能な防御戦略に基づいて防御戦略を実装します。違いは、この戦略では、モバイルアプリケーションを使用して取得されたfacebookアクセストークン文字列を含むfb_access_tokenというHTTPヘッダーを利用するということです。

これを知ると、コードはかなり簡単です。

ファイルのconfig/initializersディレクトリに、次の行を追加します。私は私のfb_api_strategyと呼んでいました。RB:

config.warden do |manager| 
    manager.default_strategies(:scope => :user).unshift :fb_database_authenticatable 
    end 

を使用すると、いずれかのFBの電子メールに基づいて既存のユーザーをユーザーを作成したり、見つけることができるようにするには、追加:

設定/初期化子で
# authentication strategy to support API authentication over the webservice 
# via facebook 

require 'devise/strategies/database_authenticatable' 
require 'fb_graph' 
require 'warden' 

module Devise 
    module Strategies 
    class FbMobileDatabaseAuthenticatable < Authenticatable 
    def valid? 
    # if we have headers with the facebook access key 
    !!request.headers["fb_access_token"] 
    end 

    def authenticate! 
    token = request.headers["fb_access_token"] 
    fbuser = FbGraph::User.me(token) 
    fbuser = fbuser.fetch 

    user = User.find_for_facebook_mobile_client(fbuser.email) 

    # this either creates a new user for the valid FB account, or attaches 
    # this session to an existing user that has the same email as the FB account 

    if !!user && validate(user) { true } 
     user.after_database_authentication 
     success!(user) 
    elsif !halted? || !user 
     fail(:invalid) 
     end 
     end 
    end 
    end 
end 

Warden::Strategies.add(:fb_database_authenticatable, 
         Devise::Strategies::FbMobileDatabaseAuthenticatable) 

、devise.rbするには、以下の追加ユーザーモデルに次

def self.find_for_facebook_mobile_client(fb_email) 
    if user = User.where(:email => fb_email).first 
     user 
    else 
     User.create!(:email => fb_email, :password => Devise.friendly_token[0,20]) 
    end 
    end 

私はfb_database_authenticatableが正確名前だとは思わないが、私は読者の練習としてそれを残しておきます。別の課題は、FBアクセストークンのキャッシュ/格納であり、おそらく各呼び出しでRTからFBを避けることです。ほとんどの人がやりたいと思うFB認証を両側で行うと、モバイルアプリとレールアプリからのアクセストークンが異なることに注意してください。これはおそらくキャッシングスキームに影響します。

私はそれをすると思います - ハッピーコーディング。

+2

何か:FBのアカウントを使用するための基本的な権限を電子メールアドレスを入力しないでください。ユーザーに明示的にこの許可を求める必要があります。 – beeudoublez

+0

良い点@beeudoublez、それはまさに私のアプリでやったことです。 – Matt

0

あなたはXcodeの4.3.2あなたが使用することができ でリクエストヘッダを設定する場合:

[request setValue:@"12345" forHTTPHeaderField:@"fbaccesstoken"]; 

いますが、使用することはできません。注意すべき

[request setValue:@"12345" forHTTPHeaderField:@"fb_access_token"]; // does NOT get set 
関連する問題