如何防止Firebase中同一用户的多个帐户?

如何防止Firebase中同一用户的多个帐户?,firebase,flutter,firebase-authentication,Firebase,Flutter,Firebase Authentication,我们正在开发一个应用程序使用颤振和探索Firebase进行身份验证,我们计划为最终用户提供以下身份验证机制 通过OTP登录 社交登录(Facebook/Google) 但在下面的场景中,存在一个问题 用户通过OTP登录(创建一个新帐户),假设U1(用户Id)和M1(移动) U1-->M1 现在,在另一天,同一个用户尝试通过FaceBook登录(我们不会通过社交登录获得手机),只有电子邮件会在那里,现在将为同一个用户创建一个新帐户 U2----->E1 如何防止在步骤2(U2)创建的帐户作为同

我们正在开发一个应用程序使用颤振和探索Firebase进行身份验证,我们计划为最终用户提供以下身份验证机制

  • 通过OTP登录
  • 社交登录(Facebook/Google)
  • 但在下面的场景中,存在一个问题

  • 用户通过OTP登录(创建一个新帐户),假设U1(用户Id)和M1(移动)

    U1-->M1

  • 现在,在另一天,同一个用户尝试通过FaceBook登录(我们不会通过社交登录获得手机),只有电子邮件会在那里,现在将为同一个用户创建一个新帐户

    U2----->E1

  • 如何防止在步骤2(U2)创建的帐户作为同一用户

    尝试探索,在OTP验证后通过电话号码更新用户配置文件,以防社交登录,但看起来无法添加电话号码,以防该号码的帐户已存在

    如果已存在具有给定电话号码的帐户,则引发FirebaseAuthUserCollisionException


    有人能帮忙吗?任何人在使用Firebase身份验证时都会遇到类似的问题?

    您需要找到一种方法来确定这是同一个用户,然后


    识别来自同一用户的帐户的惯用方法是通过其电子邮件地址。这意味着您必须要求电话验证用户向提供电子邮件地址,然后。

    我能够解决这个问题

    1. Login Social account (Account_2)
    2. Try to link Mobile No
        If(Success)
           Account (Step1) updated with Mobile No
        Else
           Login with Mobile No (Account_1)
           Link Social account (Account_2) created in step1 with Account_1
    
    java脚本代码示例:

        <script>
      var firebaseConfig = {
        apiKey: "XXXX",
        authDomain: "XXXXXX",
        databaseURL: "XXXXXX",
        projectId: "XXXXXX",
        storageBucket: "XXXXXXXXX",
        messagingSenderId: "XXXXXXX",
        appId: "XXXXXXXX",
        measurementId: "XXXXXXXXXXXX"
      };
    
      firebase.initializeApp(firebaseConfig);
      firebase.analytics();
    
    
    var provider = new firebase.auth.FacebookAuthProvider;
    
    var phoneAuthProvider = new firebase.auth.PhoneAuthProvider;
    
    firebase.auth().useDeviceLanguage();
    
    provider.setCustomParameters({
      'display': 'popup'
    });
    
    var globalCred ;
    
    
    firebase.auth().signInWithPopup(provider).then(function(result) {
    
      var token = result.credential.accessToken;
    
      globalCred = result.credential;
    
      console.log("GLOBAL :" + globalCred);
    
      var user = result.user;
    
      var prevUser = firebase.auth().currentUser; //Logged in via FB
      
      console.log(prevUser);
    
      
      if (!user.phoneNumber) {
          // Ask user for phone number.
          var phoneNumber = window.prompt('Provide your phone number');
          // You also need to provide a button element signInButtonElement
          // which the user would click to complete sign-in.
          // Get recaptcha token. Let's use invisible recaptcha and hook to the button.
          var appVerifier = new firebase.auth.RecaptchaVerifier(
              signInButtonElement, {size: 'invisible'});
          // This will wait for the button to be clicked the reCAPTCHA resolved.
          return result.user.linkWithPhoneNumber(phoneNumber, appVerifier)
            .then(function(confirmationResult) {
              // Ask user to provide the SMS code.
              var code = window.prompt('Provide your SMS code');
              // Complete sign-in.
              return confirmationResult.confirm(code);
            })
        }
    
    }).catch(function(error) {
    
      var errorCode = error.code;
      var errorMessage = error.message;
    
      var email = error.email;
    
      var credential = error.credential;
    
      if(errorCode == 'auth/credential-already-in-use'){
          // Merge accounts      
          console.log("Trying Linking");  
    
          var prevUser = firebase.auth().currentUser;
    
          prevUser.delete().then(function() {
            console.log("FB user deleted");
          }).catch(function(error) {
            // An error happened.
            console.log("Error in FB user deletion");
          });
    
          firebase.auth().signInWithCredential(credential).then(function(result) {
            console.log("Sign In Success using Phone", result);
            var currentUser = result.user;
    
              firebase.auth().currentUser.linkWithCredential(globalCred);
    
              });
    
          }).catch(function(error) {
            // If there are errors we want to undo the data merge/deletion
            console.log("Sign In Error", error);
            //repo.set(prevUser, prevUserData);
          });
    
    
      }
    
    }); 
    
    </script>
    
    
    var firebaseConfig={
    apiKey:“XXXX”,
    authDomain:“XXXXXX”,
    数据库URL:“XXXXXX”,
    projectId:“XXXXXX”,
    storageBucket:“XXXXXXXXX”,
    messagingSenderId:“XXXXXXX”,
    appId:“XXXXXXXX”,
    度量标准:“XXXXXXXXXX”
    };
    firebase.initializeApp(firebaseConfig);
    firebase.analytics();
    var provider=new firebase.auth.FacebookAuthProvider;
    var phoneAuthProvider=new firebase.auth.phoneAuthProvider;
    firebase.auth().useDeviceLanguage();
    provider.setCustomParameters({
    “显示”:“弹出窗口”
    });
    var globalCred;
    firebase.auth().signInWithPopup(提供程序)。然后(函数(结果){
    var token=result.credential.accessToken;
    globalCred=result.credential;
    console.log(“全局:+globalCred”);
    var user=result.user;
    var prevUser=firebase.auth().currentUser;//通过FB登录
    console.log(prevUser);
    如果(!user.phoneNumber){
    //询问用户的电话号码。
    var phoneNumber=window.prompt('提供您的电话号码');
    //您还需要提供一个按钮元素SigninButtoElement
    //用户将单击以完成登录。
    //获取recaptcha令牌。让我们使用不可见的recaptcha并钩住按钮。
    var appVerifier=new firebase.auth.RecaptchaVerifier(
    SigninButtoneElement,{size:'不可见'});
    //这将等待单击该按钮,以解决reCAPTCHA问题。
    返回result.user.linkWithPhoneNumber(phoneNumber,appVerifier)
    .然后(函数(确认结果){
    //请用户提供短信代码。
    var code=window.prompt('提供您的SMS代码');
    //完成登录。
    返回确认结果。确认(代码);
    })
    }
    }).catch(函数(错误){
    var errorCode=error.code;
    var errorMessage=error.message;
    var email=error.email;
    var-credential=error.credential;
    如果(errorCode=='auth/credential已在使用'){
    //合并帐户
    log(“尝试链接”);
    var prevUser=firebase.auth().currentUser;
    prevUser.delete()。然后(函数(){
    console.log(“FB用户已删除”);
    }).catch(函数(错误){
    //发生了一个错误。
    console.log(“FB用户删除错误”);
    });
    firebase.auth().signInWithCredential(凭证)。然后(函数(结果){
    console.log(“使用电话登录成功”,结果);
    var currentUser=result.user;
    firebase.auth().currentUser.linkWithCredential(globalCred);
    });
    }).catch(函数(错误){
    //如果出现错误,我们希望撤消数据合并/删除
    console.log(“登录错误”,错误);
    //repo.set(prevUser,prevUserData);
    });
    }
    }); 
    
    是的,但将电子邮件添加到电话验证帐户本质上是异步的(必须向电子邮件发送验证链接,一旦用户单击该链接,thn只能添加该电子邮件),用户可以随时注销并登录社交网站(Google/Facebook)。是否有任何方法可以在社交登录期间添加电话号码,然后将此帐户链接到以前的帐户(电话验证)?根据您解释的流程,将始终创建两个帐户,因为没有共同因素可以识别号码和电子邮件是同一用户。没有办法在默认情况下创建两个帐户。如果用户使用社交登录登录,请添加一项功能,将手机号码与帐户关联,然后根据帐户链接文档链接这两个帐户。当用户使用移动otp登录时,可以选择将其社交帐户与其链接。。