firebaseui-web: Is it safe for the merge conflict process of anonymous upgrade to be handled client side?

Is it safe for the merge conflict process of anonymous upgrade to be handled client side? I already have the code working, however, the part where you copy the old data from anonymous user and update it to the new user requires writing to database, is it safe to have client handle the code?

I tried to move the code to Cloud Functions and have Cloud Functions take care of the database writing to Cloud Firestore, but it does not seems to be possible to move all of the code into one Cloud Functions because return firebase.auth().signInWithCredential(cred); needs to be handled by the client and saving anonymous user’s credential on local variable to pass to the Cloud Functions sounds dangerous because user can just manipulate the credential and send the wrong credential to Cloud Functions.

What’s the best way to do this?

The entire workflow of handling merge conflict of anonymous user upgrading that I am talking about is as followed:

// signInFailure callback must be provided to handle merge conflicts which
    // occur when an existing credential is linked to an anonymous user.
    signInFailure: function(error) {
      // For merge conflicts, the error.code will be
      // 'firebaseui/anonymous-upgrade-merge-conflict'.
      if (error.code != 'firebaseui/anonymous-upgrade-merge-conflict') {
        return Promise.resolve();
      }
      // The credential the user tried to sign in with.
      var cred = error.credential;
      // If using Firebase Realtime Database. The anonymous user data has to be
      // copied to the non-anonymous user.
      var app = firebase.app();
      // Save anonymous user data first.
      return app.database().ref('users/' + firebase.auth().currentUser.uid)
          .once('value')
          .then(function(snapshot) {
            data = snapshot.val();
            // This will trigger onAuthStateChanged listener which
            // could trigger a redirect to another page.
            // Ensure the upgrade flow is not interrupted by that callback
            // and that this is given enough time to complete before
            // redirection.
            return firebase.auth().signInWithCredential(cred);
          })
          .then(function(user) {
            // Original Anonymous Auth instance now has the new user.
            return app.database().ref('users/' + user.uid).set(data);
          })
          .then(function() {
            // Delete anonymnous user.
            return anonymousUser.delete();
          }).then(function() {
            // Clear data in case a new user signs in, and the state change
            // triggers.
            data = null;
            // FirebaseUI will reset and the UI cleared when this promise
            // resolves.
            // signInSuccessWithAuthResult will not run. Successful sign-in
            // logic has to be run explicitly.
            window.location.assign('<url-to-redirect-to-on-success>');
          });

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 15 (7 by maintainers)

Most upvoted comments

Hey @christopherread, you can’t call auth.currentUser.linkWithCredential(credential) as it will fail. We try to do that first on your behalf but it will fail if the credential belongs to an existing user. This is what we call a merge conflict and you have to manually copy the data from one use to the other. You could sign in directly with the credential in the error but you would lose the current anonymous auth user.