使用“每个电子邮件地址一个帐户”时出现 FirebaseAuthInvalidCredentialsException

Posted

技术标签:

【中文标题】使用“每个电子邮件地址一个帐户”时出现 FirebaseAuthInvalidCredentialsException【英文标题】:FirebaseAuthInvalidCredentialsException when using "One account per email address" 【发布时间】:2016-10-03 20:19:14 【问题描述】:

...如果您不允许多个帐户使用同一电子邮件 地址,用户无法创建使用 电子邮件地址为 ex@gmail.com 的 Google 帐户(如果已有) 使用电子邮件地址 ex@gmail.com 和 密码。

我能够使用 Google 提供商登录已通过电子邮件提供商注册的同一电子邮件,因此 Google 提供商替换了电子邮件提供商,然后后者无法使用 FirebaseAuthInvalidCredentialsException 登录:密码无效或用户没有密码。

重现步骤:

向电子邮件提供商注册 -> 退出 -> 使用 Google 提供商登录 -> 退出

基本上它不应该允许将一个提供商替换为另一个并抛出 FirebaseAuthUserCollisionException: The email address is already in use by another account.

我用于登录/注销的一些代码:

  public void signUpEmail(String email, String password) 
    mFirebaseAuth.createUserWithEmailAndPassword(email, password)
        .addOnCompleteListener(this, task -> 
          if (!task.isSuccessful()) 
            Log.e("signUpWithEmail", task.getException());
          
        );
  

  private void firebaseAuthWithGoogle(GoogleSignInAccount acct) 
    AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
    mFirebaseAuth.signInWithCredential(credential)
        .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() 
          @Override public void onComplete(@NonNull Task<AuthResult> task) 
          if (!task.isSuccessful()) 
            Log.e("signInWithCredential", task.getException());
          
        
    );
  

  public void signInEmail(String email, String password) 
    mFirebaseAuth.signInWithEmailAndPassword(email, password)
        .addOnCompleteListener(this, task -> 
          if (!task.isSuccessful()) 
            Log.e("signInWithEmail", task.getException());
          
      );
  

  public void signOut() 
    Auth.GoogleSignInApi.signOut(mGoogleApiClient);
    mFirebaseAuth.signOut();
    startSignInActivity();
  

谢谢!

【问题讨论】:

很多可能取决于这里的代码。您可以分享任何最小但完整的内容吗? 添加了一些代码和一些说明。 对于您从 firebase 获得的报价,您能否出示您的参考资料。我在网上找不到它 【参考方案1】:

为了优化登录 UI 步骤并增强帐户安全性,Firebase 身份验证具有“受信任的提供者”的概念,其中身份提供者也是电子邮件服务提供者。例如,Google 是 @gmail.com 地址的可信提供商,Yahoo 是 @yahoo.com 地址的可信提供商,而 Microsoft 是 @outlook.com 地址的可信提供商。

在“每个电子邮件地址一个帐户”模式下,Firebase 身份验证尝试根据电子邮件地址关联帐户。如果用户从受信任的提供商处登录,则该用户会立即登录该帐户,因为我们知道该用户拥有该电子邮件地址。

如果存在具有相同电子邮件地址但使用其他凭据(例如密码或不受信任的提供商)创建的现有帐户,则出于安全原因会删除以前的凭据。

网络钓鱼者(不是电子邮件地址的所有者)可能会创建初始帐户 - 删除初始凭据会阻止网络钓鱼者之后访问该帐户。合法用户可以通过密码重置流程设置密码,她需要证明自己拥有该电子邮件地址。

【讨论】:

我相信这可以解释为什么 Google 登录会覆盖电子邮件地址提供商凭据。 我没有看到 ios 有这种行为。是不是只有安卓才能做到这一点? 在 Anroid/iOS/Web 上的行为是相同的。【参考方案2】:

每个电子邮件地址的多个帐户将为使用同一电子邮件的不同提供商创建一个具有不同 uid 的新用户。

重新创建:

    使用谷歌邮箱 x@x 登录 使用 facebook 电子邮件 x@x 登录 创建电子邮件密码帐户 x@x

现在您将获得 3 个不同的用户。

如果您对每封电子邮件使用强烈推荐的单一帐户,则上述 3 个提供商将属于同一用户(一个 uid)。

当您第一次创建 google 帐户 x@x 并尝试使用电子邮件 x@x 使用新的 facebook 帐户登录时,您将收到需要链接才能继续的错误消息。然后,您必须登录第一个 google 用户并将新的 facebook 用户链接到它。

【讨论】:

谢谢,问题是我得到了 FirebaseAuthInvalidCredentialsException 而不是链接所需的错误,所以不清楚出了什么问题 我明白了,我现在明白你的问题了。我认为在每封电子邮件一个帐户中,这可能是有意的。当您使用不同的提供商使用同一电子邮件登录时,通常会触发链接。然而,这是一个特例。由于 Google 电子邮件已经过验证,而在这种情况下电子邮件密码提供商没有经过验证,因此您无需链接到您的电子邮件帐户即可直接登录。但是,我会检查被删除的密码提供程序是否也是这种预期行为的一部分。 @bojeil 当你用谷歌登录时,它确实会删除密码。我知道这背后的安全原因。问题是它是默默完成的。而且您无法提醒用户他的密码将被删除。作为一种解决方法,我正在考虑更改我的身份验证以允许每封电子邮件有多个帐户。但是由于每对电子邮件/登录方法都将被视为不同的帐户,因此具有不同的 UID,因此我必须使用用户的电子邮件作为用户 ID 来将用户数据存储在我的 Firestore 中。这会在某些 Firestore 安全规则案例中引起任何麻烦吗? 是的,那会是个问题。问题是有人可能会占用您的电子邮件。我可以使用您的电子邮件和密码设置一个帐户。然后我等你创建你的帐户(想象一下它是一个流行的应用程序)。如果我的密码保留在帐户上,那么我可以完全访问您的帐户。如果您绕过此措施并允许通过安全规则访问两个帐户(通过电子邮件键入帐户),那么攻击者也将可以访问真实用户的数据。

以上是关于使用“每个电子邮件地址一个帐户”时出现 FirebaseAuthInvalidCredentialsException的主要内容,如果未能解决你的问题,请参考以下文章

创建表时出现 Sql 错误 - Firebird

颤振:致命错误:找不到模块“firebase_analytics”

退出时未调用Angular AuthGuard CanActivate - Firebase Auth

运行 adb 命令时出现问题 / 使用平板设备进行开发时出现问题

使用 FolderBrowserDialog 时出现异常

使用串行插件时出现 Ionic Capacitor Android 错误 - 连接到外部设备时出现 Cordova_not_available