ユーザーがFacebook、Twitter、Githubなどの複数の異なる認証プロバイダーを使用してFirebaseアプリケーションに対して認証できるようにしたい。認証されたら、使用した認証方法に関係なく、ユーザーが同じアカウントにアクセスできるようにします。
つまり、アプリ内で複数の認証方法を1つのアカウントにマージしたいのです。 Firebaseアプリでこれを行うにはどうすればよいですか?
Update(20160521):Firebaseが Firebase Authentication 製品のメジャーアップデートをリリースしました。これで、1人のユーザーが、サポートされているさまざまなプロバイダーのアカウントをリンクできるようになりました。この機能の詳細については、 iOS 、 Web および Android のドキュメントを参照してください。以下の答えは歴史的な理由のために残されています。
コアFirebaseサービスは、認証のためのいくつかの方法を提供します: https://www.firebase.com/docs/security/authentication.html
Firebaseはその中心で、認証にセキュアなJWTトークンを使用します。 JWTトークンの生成につながるもの(独自のサーバーでJWTライブラリを使用するなど)は、Firebaseに対してユーザーを認証するために機能するため、認証プロセスを完全に制御できます。
Firebaseは、これらのトークンを生成する1つの方法であるFirebase Simple Loginと呼ばれるサービスを提供します(これにより、Facebook、Twitterなどの認証が提供されます)。これは、サーバーがなくてもすぐに稼働できるようにする一般的な認証シナリオを対象としていますが、認証する唯一の方法ではなく、包括的なソリューションを意図したものでもありません。
Firebase Simple Loginを使用して複数のプロバイダーでログインできるようにするための1つの方法を次に示します。
実際には、TwitterとFacebookの両方の認証を有効にする(または、ユーザーが一方のアカウントを作成してから、もう一方を追加できるようにする)と想定すると、セキュリティルールは次のようになります。
{
"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をユーザーデータとアクションのプライマリストアとして使用します。上記は、ユーザーマッピングのデータを制限および検証するため、同じFacebook、Twitterなどを既に持っている適切なユーザーのみがデータを書き込むことができます。/users/$userid/(facebook-id|Twitterの下のユーザーID -id | etc-id)。
この方法を使用すると、すぐに立ち上げて実行できます。ただし、複雑なユースケースがあり、認証エクスペリエンスを完全に制御したい場合は、独自のサーバーで独自の認証コードを実行できます。 everyauth や passport など、これを行うために使用できる多くの便利なオープンソースライブラリがあります。
サードパーティの認証プロバイダーを使用して認証することもできます。たとえば、 Singly を使用できます。これは、サーバー側のコードを記述する必要なく、すぐに使用できるさまざまな統合機能を備えています。
私はこの投稿が数か月続くことを知っていますが、この問題に直面したとき、コードをより柔軟にするために多くの時間を費やしました。上記の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でログインしたときに最初に検索する情報はまだです... userMappings ' ユーザー のメインアカウントを指します ユーザー。 FacebookまたはTwitterでログインした後、メインユーザーアカウントを検索できます。に ユーザー データにアクセスできるuserMappingのリストを保持します。
新しいユーザーを作成するときは、アカウントを作成する必要があります ユーザー 最初。のユーザーのID ユーザー 何でもいいですセキュリティルールを追加することなく、Google、Githubなどのより多くのログイン方法を提供できるため、これは柔軟性があります。
これを処理するangularfireデコレータを作成しました: angularfire-multi-auth
私はかなりの時間を費やして良い解決策を考えてきましたが、IMHOがどのプロバイダーからでも登録できるようにするのは混乱を招くだけです。私のフロントエンドでは、常にメール登録を求めています。たとえば、facebookやgoogle +でログインしているユーザーは、メールを通知するときに同じユーザーとしてログに記録されます。
このようにして、Kumaによって提案されたサンプルデータは、userMappingsを複製する必要がありません。
サンプルデータストア:
userMappings
|---facebook:777
| |---user:"123"
|---Twitter:888
|---user:"123"
users
|---123
|---user data