我希望用户能够使用多个不同的身份验证提供程序(例如 Facebook、Twitter 或 Github)对我的 Firebase 应用程序进行身份验证。一旦通过身份验证,我希望用户无论使用哪种身份验证方法都可以访问同一个帐户。
换句话说,我想在我的应用程序中将多个身份验证方法合并到一个帐户中。如何在 Firebase 应用中执行此操作?
我希望用户能够使用多个不同的身份验证提供程序(例如 Facebook、Twitter 或 Github)对我的 Firebase 应用程序进行身份验证。一旦通过身份验证,我希望用户无论使用哪种身份验证方法都可以访问同一个帐户。
换句话说,我想在我的应用程序中将多个身份验证方法合并到一个帐户中。如何在 Firebase 应用中执行此操作?
更新(20160521): Firebase 刚刚发布了其Firebase 身份验证产品的重大更新,现在允许单个用户链接来自各种受支持提供商的帐户。要了解有关此功能的更多信息,请阅读iOS、Web和Android的文档。下面的答案是出于历史原因留下的。
核心 Firebase 服务提供了多种身份验证方法: https ://www.firebase.com/docs/security/authentication.html
Firebase 的核心是使用安全的 JWT 令牌进行身份验证。任何导致生成 JWT 令牌的事情(例如在您自己的服务器上使用 JWT 库)都可以向 Firebase 验证您的用户,因此您可以完全控制身份验证过程。
Firebase 提供了一个名为 Firebase 简单登录的服务,它是生成这些令牌的一种方式(这提供了我们的 Facebook、Twitter 等身份验证)。它适用于常见的身份验证场景,这样您就可以在没有服务器的情况下快速启动和运行,但这不是唯一的身份验证方式,也不是一个全面的解决方案。
这是允许使用 Firebase 简单登录与多个提供商一起登录的一种方法:
在实践中,安全规则可能如下所示,假设您希望同时启用 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)"
}
}
}
}
在此示例中,您存储一个全局用户 ID(可以是您选择的任何内容)并维护 Facebook、Twitter 等身份验证机制与主要用户记录之间的映射。为每个用户登录后,您将从用户映射中获取主要用户记录,并将该 ID 用作用户数据和操作的主要存储。以上还限制和验证用户映射中的数据,以便只能由在 /users/$userid/(facebook-id|twitter -id|etc-id)。
这种方法可以让您快速启动并运行。但是,如果您有一个复杂的用例并希望完全控制身份验证体验,您可以在自己的服务器上运行自己的身份验证代码。您可以使用许多有用的开源库来执行此操作,例如everyauth和passport。
您还可以使用 3rd 方身份验证提供程序进行身份验证。例如,您可以使用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 的用户将指向users中的主帐户。因此,通过 Facebook 或 Twitter 登录后,我们可以查找主用户帐户。在用户中,我们保留可以访问其数据的 userMapping 列表。
创建新用户时,我们必须先在用户中创建一个帐户。users 中的用户id可以是我们想要的任何东西。这是灵活的,因为我们可以提供更多的登录方式,如谷歌、Github,而无需添加更多的安全规则。
我刚刚创建了一个 angularfire 装饰器来为我们处理这个问题:angularfire-multi-auth
我花了很多时间思考一个好的解决方案,恕我直言,能够从任何提供商处注册只是令人困惑。在我的前端,我总是要求进行电子邮件注册,例如,使用 facebook 和 google+ 登录的用户在通知他的电子邮件时会以同一用户的身份登录。
这样,Kuma 提出的 Sample Data 就不需要复制 userMappings。
示例数据存储:
userMappings
|---facebook:777
| |---user:"123"
|---twitter:888
|---user:"123"
users
|---123
|---user data