54

Facebook、Twitter、Githubなどの複数の異なる認証プロバイダを使用して、ユーザーがFirebaseアプリケーションを認証できるようにしたい。一度認証されると、どの認証方法を使用していても、ユーザーは同じアカウントにアクセスできるようになります。Firebaseで複数のソーシャルサービスでログインするにはどうしたらいいですか?

つまり、複数の認証方法をアプリ内の1つのアカウントにマージしたいと思います。 Firebaseアプリケーションでこれを行うにはどうすればいいですか?

答えて

55

更新(20160521):Firebaseは今、単一のユーザーがさまざまなサポートプロバイダからアカウントをリンクすることができますそのFirebase Authentication製品へのメジャーアップデートをリリースしました。この機能の詳細については、iOSWebおよびAndroidのドキュメントを参照してください。以下の答えは歴史的な理由から残されています。


コアFirebaseサービスは、認証のためにいくつかの方法であって、そのコアにおいて https://www.firebase.com/docs/security/authentication.html

は、Firebase認証にセキュアJWTトークンを使用します。 JWTトークンの生成につながるもの(自分のサーバでJWTライブラリを使用するなど)は、Firebusへのユーザの認証に使用されるため、認証プロセスを完全に制御できます。

FirebaseはFirebase Simple Loginと呼ばれるサービスを提供しています。これは、これらのトークンを生成する方法の1つです(Facebook、Twitterなどの認証を提供します)。これは、共通の認証シナリオを対象としているため、サーバを使わずに素早く立ち上げることができますが、認証する唯一の方法ではなく、包括的なソリューションになることは意図されていません。

  1. ストア1つの正規のユーザー各ユーザーの識別子、および その1つの標準的なIDと、各プロバイダ固有の識別子のマッピング:

    はここFirebase単純なログインを使用して複数のプロバイダとのログインを可能にするための一つのアプローチです。

  2. 与えられたユーザーアカウントのいずれかの資格情報に一致するようにセキュリティルールを更新します。実際に

、セキュリティルールを使用すると、TwitterやFacebookの両方の認証を有効(またはユーザーが1つのアカウントを作成することができますし、後で他を追加)したいと仮定すると、次のようになります。

{ 
    "users": { 
    "$userid": { 
     // Require the user to be logged in, and make sure their current credentials 
     // match at least one of the credentials listed below, unless we're creating 
     // a new account from scratch. 
     ".write": "auth != null && 
     (data.val() === null || 
     (auth.provider === 'facebook' && auth.id === data.child('facebook/id').val() || 
     (auth.provider === 'twitter' && auth.id === data.child('twitter/id').val()))" 
    } 
    }, 
    "user-mappings": { 
    // Only allow users to read the user id mapping for their own account. 
    "facebook": { 
     "$fbuid": { 
     ".read": "auth != null && auth.provider === 'facebook' && auth.id === $fbuid", 
     ".write": "auth != null && 
      (data.val() == null || 
      root.child('users').child(data.val()).child('facebook-id').val() == auth.id)" 
     } 
    }, 
    "twitter": { 
     "$twuid": { 
     ".read": "auth != null && auth.provider === 'twitter' && auth.id === $twuid", 
     ".write": "auth != null && 
      (data.val() == null || 
      root.child('users').child(data.val()).child('twitter-id').val() == auth.id)" 
     } 
    } 
    } 
} 

この例では、1つのグローバルユーザーID(任意のものを選択できます)を保存し、Facebook、Twitterなどの認証メカニズムとプライマリユーザーレコードとのマッピングを維持します。各ユーザーのログイン時に、ユーザーマッピングからプライマリユーザーレコードを取得し、そのIDをユーザーデータとアクションのプライマリストアとして使用します。上の例では、/ users/$ userid /(facebook-id | twitter)の下に同じFacebook、TwitterなどのユーザーIDを持つ適切なユーザーのみが書き込むことができるように、ユーザーマッピングのデータを制限して検証します。 -id | etc-id)。

この方法を使用すると、すぐに起動して実行できます。しかし、複雑な使用例があり、認証の経験を完全に制御したい場合は、自分のサーバーで独自の認証コードを実行することができます。これには、everyauthpassportのような、役立つオープンソースライブラリがあります。

サードパーティの認証プロバイダを使用して認証することもできます。たとえば、Singlyを使用することができます。これには、サーバー側のコードを記述する必要がなく、すぐに使用できる統合機能が用意されています。

+1

私はここで見つけるこの戦略についてのあなたのためのいくつかの質問を持っている:http://stackoverflow.com/questions/22886053/can-the-firebase-auth-object -handle-simultaneous-authentication-types –

+0

'.child( 'twitter/id').val()'と '.child( 'twitter-id')。val()'の違いはわかりません。両方の異なる参照ですか?私はそれをキャッチしなかった。 – Jobsamuel

+0

マッピングの例に感謝します。 iOSでこれを行う方法に関するいくつかのコードをフォローアップすることは可能でしょうか? –

16

私はこのポストが数ヶ月存在することを知っていますが、この問題に直面したとき、コードをより柔軟にするために多くの時間がかかりました。上のAndrewコードに基づいて、私は少しコードを微調整しました。

サンプル・データストア:

userMappings 
|---facebook:777 
| |---user:"123" 
|---twitter:888 
    |---user:"123" 
users 
|---123 
    |---userMappings 
     |---facebook: "facebook:777" 
     |---twitter: "twitter:888" 

セキュリティルール:

"userMappings": { 
    "$login_id": { 
    ".read": "$login_id === auth.uid", 
    ".write": "auth!== null && (data.val() === null || $login_id === auth.uid)" 
    } 
}, 

"users": { 
    "$user_id": { 
    ".read": "data.child('userMappings/'+auth.provider).val()===auth.uid", 
    ".write": "auth!= null && (data.val() === null || data.child('userMappings/'+auth.provider).val()===auth.uid)" 
    } 
} 

のでuserMappingsはまだFacebookやTwitterでログインしたときに私たちは見上げる最初の情報であり、... 。ユーザーマッピング 'ユーザーは、ユーザーのメインアカウントを指します。だからFacebookやTwitterでのログイン後、私たちはメインのユーザーアカウントを調べることができます。 のユーザーには、そのデータにアクセスできるuserMappingのリストがあります。

新しいユーザーを作成する場合は、最初にユーザーのアカウントを作成する必要があります。。ユーザーのIDはユーザーになります。これは、セキュリティルールを追加することなく、Google、Githubのような多くのログイン方法を提供できるので柔軟性があります。

+1

これは素晴らしい解決策のように思えますが、私は疑問に思っています。つまり、適切なauth.uidを使用したリクエストは、必要な「userMapping」にアクセスできるようになります。その "userMappings"の子をルックアップすることによって必要な "ユーザ"にアクセスします(ややclunkyですが、チェック!)。 しかし、他のデータ/フィールドがあるときはどうでしょうか?「userActivity」または「userPosts」と言うと、それらのフィールドを作成したユーザだけが書き込み可能にする方法はありますか? – tydbwjiiofj23iof2jiojf2ifj3i2

+0

@MathewHuuskoV: "userActivity"または "userPosts"では、セキュリティルールをチェックすることができます事前定義された変数 "root"を使用してuserMappings内のユーザーIDを検索します。例えば。 ( "user")=== data.child( 'author')。val() ":"。投稿者のユーザーIDを含む「著者」です。 – Kuma

+1

誰かがすでにこのようなものを実装していますか?この種のソリューションのコード例はありますか? iOSアプリにEメール/パスワードまたはFacebookを使用してFirebaseログインを同じアカウントに追加したいと思います。 ユーザーのログイン方法や、以前にメールやFacebookを使用してアカウントを作成していた場合、全体が複雑になるシナリオがいくつかあります。 たとえば、ユーザーがFacebookを使用してログインしていて以前は電子メール/パスワードのみを使用してログインしていた場合、Firebaseデータベースで一致するユーザーを探すにはどうすればよいですか?またはその逆。 – andlin

2

私はちょうど私たちのためにこれを処理するためにangularfireデコレータを作成しました:angularfire-multi-auth

0

私は良い解決策に考えてかなりの時間を費やしてきた、そしてどのプロバイダから登録することができるようにする私見は、単に混乱です。私のフロントエンドでは、常に電子メールの登録を要求するので、facebookとgoogle +を使ってログインしているユーザーは、彼が自分のメールを知らせるときに同じユーザーとして記録されます。

このように、Kumaによって提案されたサンプルデータは、userMappingsを複製する必要はありません。

サンプルデータストア:

userMappings 
|---facebook:777 
| |---user:"123" 
|---twitter:888 
    |---user:"123" 
users 
|---123 
    |---user data 
関連する問題