我已经通过 sled.com 完成了这项工作。关于创建帐户和支持多个第三方帐户登录,这里存在多个问题。他们之中有一些是:
对于 sled.com,我决定放弃本地密码,因为它增加的价值很小,而且保护密码输入表单的额外成本。有许多已知的破解密码的攻击,如果你要引入密码,你必须确保它们不容易破解。您还需要将它们存储在单向哈希或类似的东西中,以防止它们被泄露。
听起来您已经选择了三个登录提供商:Facebook、Twitter 和 LinkedIn。这很好,因为这意味着您正在使用 OAuth 并与一组定义明确的可信提供者合作。我不喜欢 OpenID。剩下的问题是您是否需要支持来自同一提供商的多个第三方帐户(例如,一个本地帐户与两个 Twitter 帐户相关联)。我假设没有,但如果你这样做,你将需要在你的数据模型中适应它。
对于 Sled,我们支持使用 Facebook、Twitter 和 Yahoo! 登录。并在每个用户帐户中为每个帐户存储一个密钥:{“_id”:“djdjd99dj”,“yahoo”:“dj39djdj”,twitter:“3723828732”,“facebook”:“12837287”}。我们设置了一堆约束来确保每个第三方帐户只能链接到一个本地帐户。
如果您要允许来自同一第三方提供商的多个帐户,您将需要使用列表或其他结构来支持这一点,并使用所有其他限制来确保唯一性。
用户第一次注册您的服务时,他们首先会去第三方提供商并返回经过验证的第三方 ID。然后,您为他们创建一个本地帐户并收集您想要的任何其他信息。我们收集他们的电子邮件地址并要求他们选择一个本地用户名(我们尝试使用来自其他提供商的现有用户名预先填充表单)。拥有某种形式的本地标识符(电子邮件、用户名)对于以后的帐户恢复非常重要。
如果浏览器没有现有帐户的会话 cookie(有效或过期),并且未找到使用的第三方帐户,则服务器知道这是第一次登录。我们试图通知用户他们不仅仅是登录,而是创建一个新帐户,这样如果他们已经有一个帐户,他们希望暂停并使用现有帐户登录。
我们使用完全相同的流程来链接其他帐户,但是当用户从第三方返回时,有效会话 cookie 的存在用于区分尝试将新帐户链接到登录操作。我们只允许每种类型的一个第三方帐户,如果已经有一个链接,则阻止该操作。这应该不是问题,因为如果您已经拥有一个(每个提供商),则链接新帐户的界面将被禁用,但以防万一。
如果用户尝试链接已链接到本地帐户的新第三方帐户,您只需提示他们确认他们想要合并两个帐户(假设您可以处理与您的数据集的此类合并 - 通常更容易说比完成)。您还可以为他们提供一个特殊按钮来请求合并,但实际上,他们所做的只是链接另一个帐户。
这是一个非常简单的状态机。用户从第三方返回,并带有第三方帐户 ID。您的数据库可以处于以下三种状态之一:
- 该帐户已链接到本地帐户,并且不存在会话 cookie --> 登录
- 该帐户已链接到本地帐户并且存在会话 cookie --> 合并
- 该帐户未链接到本地帐户,并且不存在会话 cookie --> 注册
该帐户未链接到本地帐户并且存在会话 cookie --> Linking Additional account
这仍然是实验领域。我还没有看到完美的用户体验,因为大多数服务都在第三方帐户旁边提供本地密码,因此专注于“忘记我的密码”用例,而不是其他所有可能出错的情况。
对于 Sled,我们选择使用“需要帮助登录?” 当您单击时,向用户询问他们的电子邮件或用户名。我们查找它,如果我们找到匹配的帐户,则通过电子邮件向该用户发送一个链接,该链接可以自动将他们登录到服务中(一次性使用)。进入后,我们将他们直接带到帐户链接页面,告诉他们应该查看并可能链接其他帐户,并向他们显示他们已经链接的第三方帐户。