Guruprasad J Rao
Guruprasad J Rao

Reputation: 29683

User can only be linked to one identity for the given provider

I am building an application wherein user can log in anonymously and later can choose to login with Google or facebook. I've followed the steps mentioned in firebase site and also this post but still am getting an error which reads -

code: "auth/provider-already-linked",
message: "User can only be linked to one identity for the given provider."

Below are my auth.service.ts contents

@Injectable()
export class AuthService {
  user: Observable<User>;
  constructor(private afAuth: AngularFireAuth,
    private afs: AngularFirestore,
    private router: Router) {
    this.user = this.afAuth.authState
      .switchMap(user => {
        if (user) {
          return this.afs.doc<User>(`usersData/${user.uid}`).valueChanges()
        } else {
          return Observable.of(null)
        }
    });
  }

  anonymousLogin(): Promise<any>{
    return this.afAuth.auth.signInAnonymously();
  }

  get authState(): Observable<User>{
    return this.afAuth.authState.map(data => {
      return data;
    });
  }

  get currentUser(): boolean {
    return this.user !== null;
  }

  getCurrentUser(): User{
    return this.afAuth.auth.currentUser;
  }

  googleLogin() {
    const provider = new firebase.auth.GoogleAuthProvider()
    return this.oAuthLogin(provider);
  }

  facebookLogin(){
    const provider = new firebase.auth.FacebookAuthProvider();
    provider.setCustomParameters({
      'display': 'popup'
    });
    return this.oAuthLogin(provider);
  }

  private oAuthLogin(provider) {
    return this.afAuth.auth.signInWithPopup(provider)
      .then((response) => {
        if(this.getCurrentUser() !== null){
          let cred = null;
          if(response.credential.providerId === 'google.com'){
            cred = firebase.auth.GoogleAuthProvider
                   .credential(response.credential.idToken);
          }else if(response.credential.providerId === 'facebook.com'){
            cred = firebase.auth.FacebookAuthProvider
                   .credential(response.credential.authToken);
          }
          firebase.auth().currentUser
          .linkWithCredential(cred).then(function(user) {
            console.log("Anonymous account successfully upgraded", user);
          }, function(error) {
            console.log("Error upgrading anonymous account", error);
          });
        }
        this.updateUserData(response.user)
      });
  }

  private updateUserData(user) {
    const userRef: AngularFirestoreDocument<any> = this.afs.doc(`usersData/${user.uid}`);
    const data: User = {
      uid: user.uid,
      email: user.email,
      displayName: user.displayName,
      photoURL: user.photoURL,
      isAnonymous: user.isAnonymous,
      roles: {
        customer: true
      }
    };
    return userRef.set(data, {merge: true});
  }
  signOut() {
    this.afAuth.auth.signOut().then(() => {

    });
  }
}

As suggested in other posts referred I've used linkWithCredential method by passing required idToken/accessToken but it is failing to link the accounts on both providers and hence end up creating multiple accounts under Authentication-> Users.

Could anyone please point me in the right direction or am I missing anything here?

Upvotes: 5

Views: 5962

Answers (2)

bojeil
bojeil

Reputation: 30798

If you are getting auth/provider-already-linked error code, it means you have already linked the provider to that user. You can only link a provider once. You can't have multiple Facebook accounts to the same user. Only once. If you want to remove that account, you have to unlink it: firebase.auth().currentUser.unlink(firebase.auth.FacebookAuthProvider.PROVIDER_ID). You can then link a new Facebook credential to that user.

Upvotes: 6

Jason Berryman
Jason Berryman

Reputation: 4898

You can easily convert an anonymous authenticated user to a paermanent account.

View the docs here for more details. I believe that for this to work, you'll have to modify your Auth settings to allow users to login in from multiple accounts.

Upvotes: 1

Related Questions