Collegamento di più provider a un account

Questo documento spiega come collegare più provider a un singolo account Identity Platform.

Identity Platform utilizza un ID univoco per identificare gli utenti. Ciò consente agli utenti di accedi allo stesso account con fornitori diversi. Ad esempio, un utente che si è registrato inizialmente con un numero di telefono può in un secondo momento collegare il proprio Account Google e utilizzare uno dei due metodi per accedere.

Prima di iniziare

Aggiungi il supporto di due o più provider di identità alla tua app.

Attivazione o disattivazione del collegamento dell'account

L'impostazione di collegamento dell'account determina il modo in cui Identity Platform gestisce Utenti che tentano di accedere con lo stesso indirizzo email utilizzando provider diversi.

  • Collega gli account che utilizzano lo stesso indirizzo email: Identity Platform solleverà un errore se un utente prova ad accedere con un indirizzo email già in uso. Il tuo può rilevare questo errore e collegare il nuovo fornitore al proprio account esistente.

  • Creare più account per ogni provider di identità: una nuova L'account utente di Identity Platform verrà creato ogni volta che un utente accede con un altro provider.

Per scegliere un'impostazione:

  1. Vai alla pagina Impostazioni di Identity Platform nella console Google Cloud.

    Vai alla pagina Impostazioni

  2. Seleziona un'impostazione in Collegamento dell'account utente.

  3. Fai clic su Salva.

Collegamento delle credenziali del provider federato

Per collegare le credenziali da un provider federato:

  1. Accedi all'utente con qualsiasi provider o metodo di autenticazione.

  2. Recupera l'oggetto provider corrispondente al fornitore che vuoi collegare all'account dell'utente. Ad esempio:

    Versione web 9

    import { GoogleAuthProvider, FacebookAuthProvider, TwitterAuthProvider, GithubAuthProvider } from "firebase/auth";
    
    const googleProvider = new GoogleAuthProvider();
    const facebookProvider = new FacebookAuthProvider();
    const twitterProvider = new TwitterAuthProvider();
    const githubProvider = new GithubAuthProvider();

    Versione web 8

    var googleProvider = new firebase.auth.GoogleAuthProvider();
    var facebookProvider = new firebase.auth.FacebookAuthProvider();
    var twitterProvider = new firebase.auth.TwitterAuthProvider();
    var githubProvider = new firebase.auth.GithubAuthProvider();
  3. Chiedi all'utente di accedere con il fornitore che vuoi collegare. Puoi aprire una finestra popup o reindirizzare la pagina corrente. Il reindirizzamento è per gli utenti di dispositivi mobili.

    Per mostrare un popup, chiama linkWithPopup():

    Versione web 9

    import { getAuth, linkWithPopup, GoogleAuthProvider } from "firebase/auth";
    const provider = new GoogleAuthProvider();
    
    const auth = getAuth();
    linkWithPopup(auth.currentUser, provider).then((result) => {
      // Accounts successfully linked.
      const credential = GoogleAuthProvider.credentialFromResult(result);
      const user = result.user;
      // ...
    }).catch((error) => {
      // Handle Errors here.
      // ...
    });

    Versione web 8

    auth.currentUser.linkWithPopup(provider).then((result) => {
      // Accounts successfully linked.
      var credential = result.credential;
      var user = result.user;
      // ...
    }).catch((error) => {
      // Handle Errors here.
      // ...
    });

    Per reindirizzare la pagina, devi prima chiamare linkWithRedirect():

    Segui le best practice quando utilizzi signInWithRedirect, linkWithRedirect o reauthenticateWithRedirect.

    Versione web 9

    import { getAuth, linkWithRedirect, GoogleAuthProvider } from "firebase/auth";
    const provider = new GoogleAuthProvider();
    
    const auth = getAuth();
    linkWithRedirect(auth.currentUser, provider)
      .then(/* ... */)
      .catch(/* ... */);

    Versione web 8

    auth.currentUser.linkWithRedirect(provider)
      .then(/* ... */)
      .catch(/* ... */);

    Dopo aver eseguito l'accesso, l'utente verrà reindirizzato alla tua app. Quindi, potrai recuperare il risultato dell'accesso chiamando getRedirectResult():

    Versione web 9

    import { getRedirectResult } from "firebase/auth";
    getRedirectResult(auth).then((result) => {
      const credential = GoogleAuthProvider.credentialFromResult(result);
      if (credential) {
        // Accounts successfully linked.
        const user = result.user;
        // ...
      }
    }).catch((error) => {
      // Handle Errors here.
      // ...
    });

    Versione web 8

    auth.getRedirectResult().then((result) => {
      if (result.credential) {
        // Accounts successfully linked.
        var credential = result.credential;
        var user = result.user;
        // ...
      }
    }).catch((error) => {
      // Handle Errors here.
      // ...
    });

L'account dell'utente con il provider federato è ora collegato al suo account Identity Platform e l'utente può utilizzare il provider per accedere.

Collegamento delle credenziali per email e password

Per aggiungere un indirizzo email e una password a un account utente esistente:

  1. Consentire l'accesso all'utente con qualsiasi provider di identità o metodo.

  2. Chiedi all'utente di inserire un indirizzo email e una password.

  3. Crea un oggetto AuthCredential con l'indirizzo email e la password:

    Versione web 9

    import { EmailAuthProvider } from "firebase/auth";
    
    const credential = EmailAuthProvider.credential(email, password);

    Versione web 8

    var credential = firebase.auth.EmailAuthProvider.credential(email, password);
  4. Passa l'oggetto AuthCredential al metodo linkWithCredential() dell'utente che ha eseguito l'accesso:

    Versione web 9

    import { getAuth, linkWithCredential } from "firebase/auth";
    
    const auth = getAuth();
    linkWithCredential(auth.currentUser, credential)
      .then((usercred) => {
        const user = usercred.user;
        console.log("Account linking success", user);
      }).catch((error) => {
        console.log("Account linking error", error);
      });

    Versione web 8

    auth.currentUser.linkWithCredential(credential)
      .then((usercred) => {
        var user = usercred.user;
        console.log("Account linking success", user);
      }).catch((error) => {
        console.log("Account linking error", error);
      });

Le credenziali email e password sono ora collegate all'account Identity Platform dell'utente, che può utilizzarle per accedere.

Tieni presente che le credenziali di un provider federato possono essere collegate a un account email/password con un'email diversa. In questo caso, l'indirizzo email corrispondente al provider federato può essere utilizzato per creare un account email/password separato.

Gestione dell'errore account-exists-with-diversi-credential

Se hai attivato l'impostazione Collega gli account che utilizzano la stessa email in Console Google Cloud, quando un utente tenta di accedere a un provider (ad esempio SAML) con un indirizzo email già esistente per un altro provider (come Google), viene restituito l'errore auth/account-exists-with-different-credential (insieme a un oggetto AuthCredential).

Per gestire questo errore, chiedi all'utente di accedere con il provider esistente. Quindi chiama linkWithCredential(), linkWithPopup() o linkWithRedirect() per associare il nuovo fornitore al loro account utilizzando il AuthCredential.

L'esempio seguente mostra come gestire l'errore quando un utente tenta di accedi con Facebook:

Versione web 9

  import { signInWithPopup, signInWithEmailAndPassword, linkWithCredential } from "firebase/auth";

  // User tries to sign in with Facebook.
  signInWithPopup(auth, facebookProvider).catch((error) => {
  // User's email already exists.
  if (error.code === 'auth/account-exists-with-different-credential') {
    // The pending Facebook credential.
    const pendingCred = error.credential;
    // The provider account's email address.
    const email = error.customData.email;

    // Present the user with a list of providers they might have
    // used to create the original account.
    // Then, ask the user to sign in with the existing provider.
    const method = promptUserForSignInMethod();

    if (method === 'password') {
      // TODO: Ask the user for their password.
      // In real scenario, you should handle this asynchronously.
      const password = promptUserForPassword();
      signInWithEmailAndPassword(auth, email, password).then((result) => {
        return linkWithCredential(result.user, pendingCred);
      }).then(() => {
        // Facebook account successfully linked to the existing user.
        goToApp();
      });
      return;
    }

    // All other cases are external providers.
    // Construct provider object for that provider.
    // TODO: Implement getProviderForProviderId.
    const provider = getProviderForProviderId(method);
    // At this point, you should let the user know that they already have an
    // account with a different provider, and validate they want to sign in
    // with the new provider.
    // Note: Browsers usually block popups triggered asynchronously, so in
    // real app, you should ask the user to click on a "Continue" button
    // that will trigger signInWithPopup().
    signInWithPopup(auth, provider).then((result) => {
      // Note: Identity Platform doesn't control the provider's sign-in
      // flow, so it's possible for the user to sign in with an account
      // with a different email from the first one.

      // Link the Facebook credential. We have access to the pending
      // credential, so we can directly call the link method.
      linkWithCredential(result.user, pendingCred).then((userCred) => {
        // Success.
        goToApp();
      });
    });
  }
});

Versione web 8

  // User tries to sign in with Facebook.
      auth.signInWithPopup(facebookProvider).catch((error) => {
  // User's email already exists.
  if (error.code === 'auth/account-exists-with-different-credential') {
    // The pending Facebook credential.
    const pendingCred = error.credential;
    // The provider account's email address.
    const email = error.email;

    // Present the user with a list of providers they might have
    // used to create the original account.
    // Then, ask the user to sign in with the existing provider.
    const method = promptUserForSignInMethod();

    if (method === 'password') {
      // TODO: Ask the user for their password.
      // In real scenario, you should handle this asynchronously.
      const password = promptUserForPassword();
      auth.signInWithEmailAndPassword(email, password).then((result) => {
        return result.user.linkWithCredential(pendingCred);
      }).then(() => {
        // Facebook account successfully linked to the existing user.
        goToApp();
      });
      return;
    }

    // All other cases are external providers.
    // Construct provider object for that provider.
    // TODO: Implement getProviderForProviderId.
    const provider = getProviderForProviderId(method);
    // At this point, you should let the user know that they already have an
    // account with a different provider, and validate they want to sign in
    // with the new provider.
    // Note: Browsers usually block popups triggered asynchronously, so in
    // real app, you should ask the user to click on a "Continue" button
    // that will trigger signInWithPopup().
    auth.signInWithPopup(provider).then((result) => {
      // Note: Identity Platform doesn't control the provider's sign-in
      // flow, so it's possible for the user to sign in with an account
      // with a different email from the first one.

      // Link the Facebook credential. We have access to the pending
      // credential, so we can directly call the link method.
      result.user.linkWithCredential(pendingCred).then((userCred) => {
        // Success.
        goToApp();
      });
    });
  }
});

L'uso di un reindirizzamento è simile a un popup, con l'unica differenza che devi memorizzare nella cache le la credenziale tra i reindirizzamenti delle pagine (ad esempio, usando la memoria di sessione).

Tieni presente che alcuni provider, come Google e Microsoft, operano sia come email provider di identità social. I provider email sono considerati autorevoli per tutti relativi al dominio email ospitato. Ciò significa che un utente che accede con un indirizzo email ospitato dallo stesso provider non genererà mai questo errore (ad esempio, accedendo con Google utilizzando un indirizzo email @gmail.com o con Microsoft utilizzando un indirizzo email @live.com o @outlook.com).

Unisci manualmente gli account

Se un utente tenta di accedere con credenziali già collegate a un altro account utente che utilizza lo stesso provider, metodi per il collegamento dell'account non andranno a buon fine. In questo caso, dovrai riunire gli account manualmente ed eliminare il secondo account. Ad esempio:

Versione web 9

// Sign in first account.
const result1 = await signInWithCredential(auth, cred1);
const user1 = result1.user;
// Try to link a credential that belongs to an existing account
try {
  await linkWithCredential(user1, cred2);
} catch (error) {
  // cred2 already exists so an error is thrown.
  const result2 = await signInWithCredential(auth, error.credential);
  const user2 = result2.user;
  // Merge the data.
  mergeData(user1, user2);
  // Delete one of the accounts, and try again.
  await user2.delete();
  // Linking now will work.
  await linkWithCredential(user1, result2.credential);
}

Versione web 8

// Sign in first account.
const result1 = await auth.signInWithCredential(cred1);
const user1 = result1.user;
// Try to link a credential that belongs to an existing account
try {
  await user1.linkWithCredential(cred2);
} catch (error) {
  // cred2 already exists so an error is thrown.
  const result2 = await auth.signInWithCredential(error.credential);
  const user2 = result2.user;
  // Merge the data.
  mergeData(user1, user2);
  // Delete one of the accounts, and try again.
  await user2.delete();
  // Linking now will work.
  await user1.linkWithCredential(result2.credential);
}

Puoi scollegare un fornitore dall'account di un utente. L'utente non potrà più autenticarsi con quel provider.

Per scollegare un fornitore, passa l'ID fornitore al metodo unlink(). Puoi ottenere gli ID provider dei provider di autenticazione collegati a un utente dalla proprietà providerData.

Versione web 9

import { getAuth, unlink } from "firebase/auth";

const auth = getAuth();
unlink(auth.currentUser, providerId).then(() => {
  // Auth provider unlinked from account
  // ...
}).catch((error) => {
  // An error happened
  // ...
});

Versione web 8

user.unlink(providerId).then(() => {
  // Auth provider unlinked from account
  // ...
}).catch((error) => {
  // An error happened
  // ...
});

Passaggi successivi