如何允许通过多个身份验证提供程序进行注册,同时共享相同的电子邮件地址?

Gee*_*Jan 6 authentication oauth

这可能是SO和UX.se之间的一个问题.

我正在实现一个注册/登录系统,允许多种身份验证方式:使用Facebook,Twitter,Github和本地(用户名+密码)注册的社交注册.

在后端,我有一个User模型和一个Passport模型.A User可能有多个Passports,意味着User可以通过不同的方式进行身份验证(例如:通过本地登录,或通过Facebook等)

好的方法:Passports特定的一个User将永远来自不同的提供商(Facebook,推特,本地).即:Facebook护照,本地护照等.

这似乎是一种很好的方式,可以让我User account连接到多种身份验证方式.

我熟悉这可能带来的安全问题,因此要合并/合并护照,用户必须登录到两者.

好的问题.请考虑以下流程:

  1. user-a通过电子邮件user-a@gmail.com与提供商签约,比如本地用户
  2. user-a签出(或者会话已过期).
  3. 用户-a使用其他提供商登录,比如facebook.有可能是facebook帐户有一个user-a@gmail.com的电子邮件记录

目前,我已经定义emailUser-model 上的唯一.这意味着上述注册将失败,因为已经有一个User-account通过本地Passport具有所提到的电子邮件地址.

在这种情况下,最佳做法是什么?我相信必须有很多实现浮动,必须看到这个问题弹出.

选项:

  1. 警告用户无法进行身份验证,并通过其他身份验证机制向用户提及当前的电子邮件地址已经注册?这将是合理的用户友好性.
  2. 请注意,通过不同的提供商存在的用户帐户具有相同的电子邮件地址,因此将新的Passport与用户合并..我只是把它放在一个很好的衡量标准中:这是一个非常大的攻击向量,允许用户-b通过伪造电子邮件地址(通过不进行电子邮件验证的社交提供商)访问帐户
  3. 没有唯一性约束<user,email>,但是<passport, email>.这将允许创建一个新的User和关联的Passport一切顺利.现在,同一个真实的人可能有2个用户帐户:每个身份验证提供商1个.作为下一阶段,允许合并用户帐户,登录到两者并确认合并.

我倾向于3,但1更简单.我不确定,你怎么看?你以前遇到过这个吗?

Bib*_*iba 3

是的,#3。我自己已经实现了这个。您正在查看的概念是:关联多个 SSO 帐户。我的用户结构如下:

name : { 
    first:  { type: String},
    last:   { type: String }
},
emails: [{ type: String, unique: true, 'index': true }],  //all known emails as provided by SSO services. we use this to cross ref when the user uses a different SSO to login after initial setup. this avoids account dupes
sso: [{
    provider:   { type: String, required: true}, //matches the name of passport strategy name employed
    userid:     { type: String, required: true } //the specific SSO provider userID that's unique in the provider's realm
}]
Run Code Online (Sandbox Code Playgroud)

因此,在您的身份验证序列中,您可以通过电子邮件或提供商+用户 ID 组合进行查找,如果找不到 SSO 提供商,请附加它。原因是,某人可能会更新他们的电子邮件,但特定的 SSO 提供商 ID 永远不会改变。

另一种常见做法(如果在您的应用程序中有意义)是允许用户“链接”SSO 帐户。这允许您处理不同的电子邮件地址。示例:用户 FB 电子邮件是个人电子邮件,但在 LinkedIn 中,他将商业电子邮件列为主要电子邮件。遗憾的是,LinkedIn 仅通过 OAuth2 调用为您提供主要信息。