Mehrere Anbieter mit einem Konto verknüpfen

In diesem Dokument wird gezeigt, wie Sie mehrere Anbieter mit einem einzigen Identity Platform-Konto verknüpfen.

Identity Platform verwendet eine eindeutige ID, um Nutzer zu identifizieren. Auf diese Weise können sich Nutzer mit unterschiedlichen Anbietern im selben Konto anmelden. Beispielsweise kann ein Nutzer, der sich ursprünglich mit einer Telefonnummer registriert hat, später sein Google-Konto verknüpfen und sich dann auf eine der beiden Arten anmelden.

Hinweise

Fügen Sie Ihrer Anwendung zwei oder mehr Identitätsanbieter hinzu.

Kontoverknüpfung aktivieren oder deaktivieren

Mit der Kontoverknüpfungseinstellung wird festgelegt, wie Identity Platform die Nutzer behandelt, die versuchen, sich mit derselben E-Mail-Adresse über verschiedene Anbieter anzumelden.

  • Konten mit derselben E-Mail-Adresse verknüpfen: Identity Platform gibt einen Fehler aus, wenn ein Nutzer versucht, sich mit einer E-Mail-Adresse anzumelden, die bereits verwendet wird. Ihre Anwendung kann diesen Fehler erkennen und den neuen Anbieter mit seinem bestehenden Konto verknüpfen.

  • Mehrere Konten für jeden Identitätsanbieter erstellen: Jedes Mal, wenn sich ein Nutzer bei einem anderen Anbieter anmeldet, wird ein neues Identity Platform-Nutzerkonto erstellt.

So wählen Sie eine Einstellung aus:

  1. Rufen Sie in der Google Cloud Console die Seite Einstellungen der Identity Platform auf.

    Zur Seite „Einstellungen“

  2. Wählen Sie unter Kontoverknüpfung eine Einstellung aus.

  3. Klicken Sie auf Speichern.

Anmeldedaten eines föderierten Anbieters verknüpfen

So verknüpfen Sie die Anmeldedaten eines föderierten Anbieters:

  1. Melden Sie sich mit einem beliebigen Authentifizierungsanbieter oder einer Methode an.

  2. Rufen Sie das Anbieterobjekt ab, das dem Anbieter entspricht, den Sie mit dem Nutzerkonto verknüpfen möchten. Beispiel:

    Web version 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();

    Web version 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. Bitten Sie den Nutzer, sich mit dem Anbieter anzumelden, den Sie verknüpfen möchten. Sie können entweder ein Pop-up-Fenster öffnen oder die aktuelle Seite weiterleiten. Für Nutzer von Mobilgeräten ist die Weiterleitung einfacher.

    Rufen Sie linkWithPopup() auf, um ein Pop-up-Fenster einzublenden:

    Web version 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.
      // ...
    });

    Web version 8

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

    Rufen Sie zum Weiterleiten der Seite zuerst linkWithRedirect() auf:

    Folgen Sie den Best Practices zur Verwendung von signInWithRedirect, linkWithRedirect oder reauthenticateWithRedirect.

    Web version 9

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

    Web version 8

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

    Nachdem der Nutzer sich angemeldet hat, wird er zu Ihrer Anwendung zurückgeleitet. Anschließend können Sie das Anmeldeergebnis durch Aufrufen von getRedirectResult() abrufen:

    Web version 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.
      // ...
    });

    Web version 8

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

Das Nutzerkonto des föderierten Anbieters ist jetzt mit seinem Identity Platform-Konto verknüpft und kann sich über den Anbieter anmelden.

E-Mail-Adresse und Passwort als Anmeldedaten verknüpfen

So fügen Sie einem vorhandenen Nutzerkonto eine E-Mail-Adresse und ein Passwort hinzu:

  1. Melden Sie sich mit einem beliebigen Identitätsanbieter oder einer beliebigen Methode an.

  2. Fordern Sie den Nutzer zur Eingabe einer E-Mail-Adresse und eines Passworts auf.

  3. Erstellen Sie ein AuthCredential-Objekt mit der E-Mail-Adresse und dem Passwort:

    Web version 9

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

    Web version 8

    var credential = firebase.auth.EmailAuthProvider.credential(email, password);
  4. Übergeben Sie das AuthCredential-Objekt an die Methode linkWithCredential() des angemeldeten Nutzers:

    Web version 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);
      });

    Web version 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);
      });

Die E-Mail-Adresse und das Passwort sind jetzt mit dem Identity Platform-Konto des Nutzers verknüpft und können sich damit anmelden.

Die Anmeldedaten eines föderierten Anbieters können mit einem E-Mail-/Passwort-Konto mit einer anderen E-Mail-Adresse verknüpft werden. In diesem Fall kann die E-Mail-Adresse des föderierten Anbieters zum Erstellen eines separaten E-Mail-/Passwortkontos verwendet werden.

Fehler "account-exists-with-different-credential" bearbeiten

Wenn Sie in der Google Cloud Console die Einstellung Konten verknüpfen, die dieselbe E-Mail-Adresse verwenden aktiviert haben, wird der Fehler auth/account-exists-with-different-credential ausgegeben (zusammen mit einem AuthCredential-Objekt), wenn ein Nutzer versucht, sich bei einem Anbieter (z. B. SAML) mit einer E-Mail-Adresse anzumelden, die bereits für einen anderen Anbieter (z. B. Google) vorhanden ist.

Bitten Sie den Nutzer, sich beim aktuellen Anbieter anzumelden, damit dieser Fehler behoben werden kann. Rufen Sie dann linkWithCredential(), linkWithPopup() oder linkWithRedirect() auf, um den neuen Anbieter über die AuthCredential mit seinem Konto zu verknüpfen.

Das folgende Beispiel zeigt, wie dieser Fehler behoben wird, wenn ein Nutzer versucht, sich mit Facebook anzumelden:

Web version 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();
      });
    });
  }
});

Web version 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();
      });
    });
  }
});

Weiterleitungen sind ähnlich wie Pop-ups, es sei denn, Sie speichern die ausstehenden Anmeldedaten zwischen den Seitenweiterleitungen (z. B. mit Sitzungsspeicher).

Beachten Sie, dass einige Anbieter, z. B. Google und Microsoft, sowohl als E-Mail- als auch als Anbieter von sozialen Identitäten dienen. E-Mail-Anbieter gelten als vertrauenswürdig für alle Adressen, die mit ihrer gehosteten E-Mail-Domain zusammenhängen. Das bedeutet, dass sich ein Nutzer, der sich mit einer E-Mail-Adresse anmeldet, die vom selben Anbieter gehostet wird, nie diesen Fehler auslöst. Er kann sich z. B. mit einer @gmail.com-E-Mail bei Google anmelden oder bei Microsoft mit einer @live.com-oder @outlook.com-E-Mail).

Konten manuell zusammenführen

Wenn ein Nutzer versucht, sich mit Anmeldedaten eines anderen Nutzers, der bereits mit demselben Anbieter verknüpft ist, anzumelden, schlagen die integrierten Methoden des Client-SDK zur Kontoverknüpfung fehl. In diesem Fall müssen Sie die Konten manuell zusammenführen und dann das zweite Konto löschen. Beispiel:

Web version 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);
}

Web version 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);
}

Sie können die Verknüpfung zwischen einem Anbieter und dem Konto eines Nutzers aufheben. Der Nutzer kann sich nicht mehr bei diesem Anbieter authentifizieren.

Wenn Sie die Verknüpfung mit einem Anbieter aufheben möchten, übergeben Sie die Anbieter-ID an die Methode unlink(). Sie können die Anbieter-IDs der Authentifizierungsanbieter abrufen, die mit einem Nutzer verknüpft sind, aus dem Attribut providerData.

Web version 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
  // ...
});

Web version 8

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

Nächste Schritte