Kid
Kid

Reputation: 2215

I want to handle linkWithPopup and Firebase `auth/credential-already-in-use` error in this case

I read the Authenticate Using Google Sign-In with JavaScript and I cant see a solution for the error code auth/credential-already-in-use.

Basically I try to linkWithPopup but the user has already in another browser previously sign in so I cant link him, so I can simply just sign him in at this browser no linking needed.

That's why I get this error auth/credential-already-in-use

I have this code:
(The firebase.auth.currentUser is an anonymous signed in user)

onSocialLoginLink = provider => {
    const { firebase, changeUserRole } = this.props;
    firebase.auth.currentUser
        .linkWithPopup(firebase[provider])
        .then(res => {
            if (res.credential) {
                // do stuff;
            }
        })
        .catch(error => {
            if (error.code == 'auth/credential-already-in-use') {
                // Here I want to directly sign in with this credential 
                console.log('linkWithProvider Failure, error', error);
                console.log('linkWithProvider Failure, error["credential"]', error['credential']);
            } else {
                this.setState({ error });
            }
        });
};

I'm a beginner at this and I cant find in the docs how to do this. Do I first have to sign out the anonymous user before doing signInWithPopup? Is it possible to do this without user interaction, without signInWithPopup?

When I'm inside the .catch(error =... I know the prover like Gmail and the specific user Gmail address. I get that from error.credential

Or maybe this is a bad solution please advice?

Upvotes: 7

Views: 3072

Answers (3)

Marcelo Potty
Marcelo Potty

Reputation: 354

Updating @sumneuron 's answer to the new modular firebase API, linkWithPopup error doesn't returns any credential, so after digging for hours I found this issue comment that solve's it.

try {
  // logged in with an anon user
  // try to connect via popup with 3rd part
} catch (e) {
  if ( error.toString().includes("auth/credential-already-in-use")) {
      //Now we use OAuthProvider.credentialFromError
      const credential = OAuthProvider.credentialFromError(error)
      signInWithCredential(auth, credential)
  }
} finally {
  // clean up
}

Upvotes: 3

Daniel Schaefer
Daniel Schaefer

Reputation: 1

Actually, I was struggling with the same problem in Flutter but as it turned out, linkWithProvider isn't needed. All I ended up calling is:

  final appleProvider = AppleAuthProvider();
  appleProvider.addScope('email');

   await FirebaseAuth.instance.currentUser
            ?.reauthenticateWithProvider(appleProvider)
            .then((UserCredential credential) async {
       // Firebase seems to handle the rest
   });
         

Not sure if this is intential because it isn't documented anywhere but it does appear to do work.

Upvotes: 0

SumNeuron
SumNeuron

Reputation: 5198

Was just having the same issue myself. Thank you for asking. I just looked in the docs and found this which states:

auth/credential-already-in-use: Thrown if the account corresponding to the credential already exists among your users, or is already linked to a Firebase User. For example, this error could be thrown if you are upgrading an anonymous user to a Google user by linking a Google credential to it and the Google credential used is already associated with an existing Firebase Google user. An error.email and error.credential (firebase.auth.AuthCredential) fields are also provided. You can recover from this error by signing in with that credential directly via firebase.auth.Auth.signInWithCredential.

with of course the relevant link being firebase.auth.Auth.signInWithCredential.

I just tried this in my own code with something that looks like this

try {
  // logged in with an anon user
  // try to connect via popup with 3rd part
} catch (e) {
  // if code is auth already in use
  firebase.auth.Auth.signInWithCredential(e.credential)
} finally {
  // clean up
}

Upvotes: 5

Related Questions