Skip to content

Users duplicate on Firestore when I use googleSignIn

I have two ways to register a user in Firebase: through email and through Google Sign In.

I perform the user registration by email as follows:

signUp() {
  const auth = getAuth();
  const db = getFirestore();
  createUserWithEmailAndPassword(
    auth,
    this.createEmail,
    this.createPassword
  ).then(
    (userCredential) => {
      const user = userCredential.user;
      this.$router.push("/");
      addDoc(collection(db, "users"), {
        email: this.createEmail,
        name: this.createName,
      });
    },
  );
},

In other words, in addition to saving the user in Firebase Authentication, I also send their name and email to Firestore. And this is my first question:

  • Is it the most effective way to save the username and future data that will still be added to it?

Finally, login by Google is done as follows:

googleSignIn() {
  const auth = getAuth();
  const provider = new GoogleAuthProvider();
  signInWithPopup(auth, provider)
    .then((result) => {
      this.$router.push("/");
      addDoc(collection(db, "users"), {
        email: result.user.email,
        name: result.user.displayName,
      });
    })
},

Here a problem arises because if a user logs in more than once in Firebase Authentication everything is ok, but in Firebase Firestore a user is created for each new login with Google.

  • How do I handle this issue of storing users in Firestore, especially users coming from Google Login?

Answer

First, I’d move the router.push() statement below addDoc() so I can confirm that the document has been added and then user is redirected to other pages. In case of Google SignIn, you can check if the user is new by accessing the isNewUser property by fetching additional information. If true, then add document to Firestore else redirect to dashboard:

signInWithPopup(auth, provider)
  .then(async (result) => {
  
  // Check if user is new
  const {isNewUser} = getAdditionalUserInfo(result)

  if (isNewUser) {
    await addDoc(collection(db, "users"), {
      email: result.user.email,
      name: result.user.displayName,
    });
  }
  this.$router.push("/");
})

It might be a good idea to set the document ID as user’s Firebase Auth UID instead of using addDoc() which generated another random ID so it’s easier to write security rules. Try refactoring the code to this:

signInWithPopup(auth, provider)
  .then(async (result) => {
  
  // Check if user is new
  const {isNewUser} = getAdditionalUserInfo(result)
  const userId = result.user.uid

  if (isNewUser) {
    await setDoc(doc(db, "users", userId), {
      email: result.user.email,
      name: result.user.displayName,
    });
  }
  this.$router.push("/");
})