JavaScript を使用してアカウントに複数の認証プロバイダをリンクする

既存のユーザー アカウントに認証プロバイダの認証情報をリンクすることで、ユーザーが複数の認証プロバイダを使用してアプリにログインできるようになります。ログインに使用した認証プロバイダに関係なく、同じ Firebase ユーザー ID でユーザーを識別できます。たとえば、パスワードを使用してログインしたユーザーが認証情報を Google アカウントにリンクすれば、それ以降はどちらの方法でもログインできるようになります。また、匿名ユーザーが認証情報を Facebook アカウントにリンクすると、それ以降は Facebook にログインしてアプリを使用できるようになります。

準備

アプリに複数の認証プロバイダ(匿名認証も含む)のサポートを追加します。

既存のユーザー アカウントに Google や Facebook などの認証プロバイダからの認証情報をリンクするには:

  1. 任意の認証プロバイダや認証方法を使用してユーザーのログインを行います。
  2. ユーザーのアカウントにリンクするプロバイダに対応する AuthProvider オブジェクトを取得します。次に例を示します。
    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. リンク先となるプロバイダにログインするようユーザーに促します。ポップアップ ウィンドウをユーザーに表示するか、プロバイダのログインページにリダイレクトすることにより、ログインを促すことができます。モバイル デバイスではリダイレクトすることをおすすめします。
    • ポップアップ ウィンドウでログインを行う場合は、linkWithPopup を呼び出します。
      auth.currentUser.linkWithPopup(provider).then(function(result) {
        // Accounts successfully linked.
        var credential = result.credential;
        var user = result.user;
        // ...
      }).catch(function(error) {
        // Handle Errors here.
        // ...
      });
    • プロバイダのログインページにリダイレクトしてログインを行う場合は、linkWithRedirect を呼び出します。
      auth.currentUser.linkWithRedirect(provider)
        .then(/* ... */)
        .catch(/* ... */);
      ユーザーがログインしたら、元のページにリダイレクトされます。次に、ページが読み込まれるときに getRedirectResult を呼び出すことによって、ログイン結果を取得できます。
      auth.getRedirectResult().then(function(result) {
        if (result.credential) {
          // Accounts successfully linked.
          var credential = result.credential;
          var user = result.user;
          // ...
        }
      }).catch(function(error) {
        // Handle Errors here.
        // ...
      });
    ユーザーが正常にログインすると、プロバイダでのユーザー アカウントが Firebase プロジェクト内のユーザー アカウントにリンクされます。

    認証情報がすでに別のユーザー アカウントにリンクされている場合は、アカウントのリンク付けが失敗します。その場合、アプリに適した方法でアカウントと関連データの統合を行う必要があります。

    // The implementation of how you store your user data depends on your application
    var repo = new MyUserDataRepo();
    
    // Get reference to the currently signed-in user
    var prevUser = auth.currentUser;
    
    // Get the data which you will want to merge. This should be done now
    // while the app is still signed in as this user.
    var prevUserData = repo.get(prevUser);
    
    // Delete the user's data now, we will restore it if the merge fails
    repo.delete(prevUser);
    
    // Sign in user with the account you want to link to
    auth.signInWithCredential(newCredential).then(function(result) {
      console.log("Sign In Success", result);
      var currentUser = result.user;
      var currentUserData = repo.get(currentUser);
    
      // Merge prevUser and currentUser data stored in Firebase.
      // Note: How you handle this is specific to your application
      var mergedData = repo.merge(prevUserData, currentUserData);
    
      return prevUser.linkWithCredential(result.credential)
        .then(function(linkResult) {
          // Sign in with the newly linked credential
          return auth.signInWithCredential(linkResult.credential);
        })
        .then(function(signInResult) {
          // Save the merged data to the new user
          repo.set(signInResult.user, mergedData);
        });
    }).catch(function(error) {
      // If there are errors we want to undo the data merge/deletion
      console.log("Sign In Error", error);
      repo.set(prevUser, prevUserData);
    });

既存のユーザー アカウントにメールアドレスとパスワードの認証情報をリンクするには:

  1. 任意の認証プロバイダや認証方法を使用してユーザーのログインを行います。
  2. ユーザーにメールアドレスと新しいパスワードの入力を要求します。
  3. そのメールアドレスとパスワードを使って AuthCredential オブジェクトを作成します。
    var credential = firebase.auth.EmailAuthProvider.credential(email, password);
  4. ログイン ユーザーの linkWithCredential メソッドに AuthCredential オブジェクトを渡します。

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

    認証情報が別のユーザー アカウントにすでにリンクされている場合は、linkWithCredential の呼び出しが失敗します。このような場合は、アプリに適した方法でアカウントと関連データを統合する必要があります(上記の例を参照)。

アカウントから認証プロバイダのリンクを解除することで、ユーザーがそのプロバイダを使用してログインできなくなります。

ユーザー アカウントから認証プロバイダのリンクを解除するには、プロバイダ ID を unlink メソッドに渡します。ユーザーにリンクされている認証プロバイダのプロバイダ ID は providerData プロパティから取得できます。

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