Firestore + angularfire - cuenta de enlace

He tenido muchos problemas.

quiero proporcionar múltiples opciones de inicio de sesión para los usuarios. Ahora google y Facebook.
Pero cuando un usuario inicia sesión en Google e intenta iniciar sesión en Facebook, tengo un error:

An account already exists with the same email address but different sign-in credentials. Sign in using a provider associated with this email address.


Así que tengo que conectar las cuentas. No he encontrado ningún documento relevante, excepto this, que no ayuda mucho. La mejor información que pude encontrar fue stackoverflow, pero por alguna razón no fue suficiente para mí.
La solución maneja signInWithPopup, lo que me da el siguiente error:

"Unable to establish a connection with the popup. It may have been blocked by the browser." So if the popup doesn't work, I call signInWithRedirect:

private authLoginWithPopup(provider: AuthProvider) {
  this.afAuth.auth.signInWithPopup(provider)
    .then((result) => {
      this.credential = result.credential;
      this.updateUserData(result);
    })
    .catch(error => {
      if (error.code === 'auth/account-exists-with-different-credential') {
        this.mergeCredentials(error);
      } else if (error.code === 'auth/popup-blocked') {
        this.authLoginWithRedirect(new firebase.auth.GoogleAuthProvider());
      }
    });
}
Cuando salga, entrará en then y puede hacer cualquier cosa. Pero si te vuelves atrás, perderás información. Así que lo guardo en localStorage:
this.afAuth.auth.fetchProvidersForEmail(error.email).then(providers => {
  const [ provider ] = providers;
  if (provider === 'google.com') {
    const googleProvider = new firebase.auth.GoogleAuthProvider();
    googleProvider.setCustomParameters({ login_hint: error.email });
    localStorage.setItem('auth_error', JSON.stringify(error.credential));
    this.authLoginWithPopup(googleProvider);
  }
});
Lo recupero en getredirectresult:
constructor(
  private afAuth: AngularFireAuth,
  private afs: AngularFirestore,
) {
  this.afAuth.auth.getRedirectResult().then(result => {
    if (result.user) {
      this.credential = result.credential;
      const authError = JSON.parse(localStorage.getItem('auth_error'));

      if (authError) {
        localStorage.removeItem('auth_error');

        this.afAuth.auth.signInWithCredential(
          firebase.auth.GoogleAuthProvider.credential(
            null, (<any>this.credential).accessToken
          )
        )
          .then(user => {
            user.linkWithCredential(authError)
          })
          .catch(error => {
            console.log('error', error);
          });
      }
    }
  });
}
(esto plantea otro problem a. Cómo sé que es un login normal, una redirección del usuario que está conectado directamente a Google. O una redirección después de que el usuario intenta iniciar sesión en Facebook y se le pide que inicie sesión en Google debido a este error? No quiero fusionar credenciales cada vez. Pero es un problema menor. Pero me encantaría encontrar una solución aquí también.)
Pero signInWithCredential me dio este error:

linkWithCredential failed: First argument "credential" must be a valid credential.


He encontrado la "solución"here:

When calling signInWithCredential with a access token you need to call it like this:

signInWithCredential(null, token); If you are doing signInWithCredential(token) then you need to use an ID Token rather than an access token.


Intenté ambas versiones sin éxito. Segunda versión:this.afAuth.auth.signInWithCredential(firebase.auth.GoogleAuthProvider.credential((<any>this.credential).idToken))La transformación de tipo existe porque creo que hay un problem a con la definición de tipo.
Intenté insertar todo el objeto credentials, idToken como el primer parámetro, y accessToken como el segundo parámetro. Pero siempre tengo:
El primer parámetro, credencial, debe ser un credencial válido.
Mientras escribía este artículo, me di cuenta de que podría ser un problem a con linkWithCredential, no con el método signInWithCredential. Según el mensaje de error, esto debería ser obvio. Simplemente no me di cuenta porque el error de búsqueda de google me dio la solución. Así que rápidamente revisé el contenido de la variable authError. Hay métodos accessToken, providerId y signInMethod. No tokenId. Por lo tanto, traté de enviar el accessToken como argumento en lugar de todo el objeto, pero no hubo ayuda. Intenté enviarlo en null, accessToken. No sirve de nada. Traté de encontrar la documentación para el método linkWithCredential, pero no tuve suerte. Así que no sé qué espera.
He estado desperdiciando cuatro días en esto. Me cost ó mucha salud mental. ¿Alguien puede ayudarme?

Una solución para mí

puede almacenar la credencial oauth subyacente (Token ID o token de acceso): error.credential.idToken o error.credential.accessToken y su proveedor ID error.credential.providerId. Cuando vuelva a la página, puede reinicializar las credenciales, por ejemplo: firebase.auth.FacebookAuthProvider.credential(accessToken). Después de redirigir con éxito el login de Google, vincule la credencial