여러 공급업체를 하나의 계정에 연결하기

이 도움말에서는 여러 공급업체를 하나의 Identity Platform 계정에 연결하는 방법을 설명합니다.

Identity Platform은 고유 ID를 사용하여 사용자를 식별합니다. 이를 통해 사용자는 서로 다른 공급업체의 동일한 계정에 로그인할 수 있습니다. 예를 들어 처음에 전화번호로 등록한 사용자는 나중에 Google 계정을 연결한 다음 두 가지 방법 중 하나를 사용하여 로그인할 수 있습니다.

시작하기 전에

앱에 두 개 이상의 ID 공급업체에 대한 지원을 추가합니다.

계정 연결 사용 설정 또는 중지

계정 연결 설정에 따라 Identity Platform에서 서로 다른 공급업체를 통해 동일한 이메일로 로그인을 시도하는 사용자가 처리되는 방법이 결정됩니다.

  • 동일한 이메일을 사용하는 계정 연결: 사용자가 이미 사용 중인 이메일로 로그인을 시도하면 Identity Platform에서 오류가 발생합니다. 앱에서 이 오류를 발견하고 새로운 공급업체를 기존 계정에 연결할 수 있습니다.

  • 각 ID 공급업체마다 여러 계정 만들기: 사용자가 다른 공급업체로 로그인할 때마다 새로운 Identity Platform 사용자 계정이 생성됩니다.

설정을 선택하려면 다음 안내를 따르세요.

  1. Cloud Console에서 Identity Platform 설정 페이지로 이동합니다.

    설정 페이지로 이동

  2. 사용자 계정 연결에서 설정을 선택합니다.

  3. 저장을 클릭합니다.

제휴 공급업체 사용자 인증 정보 연결

제휴 공급업체의 사용자 인증 정보를 연결하는 방법은 다음과 같습니다.

  1. 인증 공급업체 또는 메서드를 사용하여 사용자를 로그인 처리합니다.

  2. 사용자 계정에 연결할 공급업체에 해당하는 공급업체 객체를 가져옵니다. 예를 들면 다음과 같습니다.

    자바스크립트

    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((result) => {
      // Accounts successfully linked.
      var credential = result.credential;
      var user = result.user;
      // ...
    }).catch((error) => {
      // Handle Errors here.
      // ...
    });

    페이지를 리디렉션하려면 먼저 linkWithRedirect()를 호출합니다.

    자바스크립트

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

    사용자가 로그인하면 앱으로 다시 리디렉션됩니다. 이를 통해 getRedirectResult()를 호출하여 로그인 결과를 검색할 수 있습니다.

    자바스크립트

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

제휴 공급업체의 사용자 계정은 Identity Platform 계정에 연결되며, 사용자는 이 공급업체를 사용하여 로그인할 수 있습니다.

이메일 및 비밀번호 인증 정보 연결

기존 사용자 계정에 이메일 주소와 비밀번호를 추가하려면 다음 안내를 따르세요.

  1. ID 공급업체 또는 메서드를 사용하여 사용자를 로그인 처리합니다.

  2. 사용자에게 이메일 주소와 비밀번호를 묻습니다.

  3. 사용자가 제공한 이메일 주소와 비밀번호로 AuthCredential 객체를 만듭니다.

    자바스크립트

    var credential = firebase.auth.EmailAuthProvider.credential(email, password);
  4. 로그인한 사용자의 linkWithCredential() 메서드에 AuthCredential 객체를 전달합니다.

    자바스크립트

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

이제 이메일 및 비밀번호 사용자 인증 정보가 사용자의 Identity Platform 계정에 연결되므로 이를 사용하여 로그인할 수 있습니다.

account-exists-with-different-credential 오류 처리

동일한 이메일을 사용하는 계정 연결 설정을 사용 설정한 경우 사용자가 기존 계정에 이미 연결된 이메일을 사용하여 공급업체로 로그인을 시도하면 Identity Platform에서 오류가 발생합니다.

이 오류를 처리하려면 사용자에게 기존 계정으로 로그인하라는 메시지를 표시합니다. 그런 다음 linkWithCredential(), linkWithPopup() 또는 linkWithRedirect()를 호출하여 새 공급업체를 계정에 연결합니다.

다음 예시는 사용자가 Facebook을 사용하여 로그인을 시도할 때 이 오류를 처리하는 방법을 보여줍니다.

자바스크립트

// User tries to sign in with Facebook.
auth.signInWithPopup(new firebase.auth.FacebookAuthProvider()).catch(err => {
  // User's email already exists.
  if (err.code === 'auth/account-exists-with-different-credential') {
    // The pending Facebook credential.
    var pendingCred = err.credential;
    // The provider account's email address.
    var email = err.email;
    // Get the sign-in methods for this email.
    auth.fetchSignInMethodsForEmail(email).then(methods => {
      // If the user has several sign-in methods, the first method
      // in the list will be the "recommended" method to use.
      if (methods[0] === 'password') {
        // TODO: Ask the user for their password.
        // In real scenario, you should handle this asynchronously.
        var 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.
      var provider = getProviderForProviderId(methods[0]);
      // 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();
        });
      });
    });
  }
});

리디렉션 사용은 세션 스토리지 등을 사용하여 페이지 리디렉션 사이에 대기 중인 사용자 인증 정보를 캐시해야 한다는 점을 제외하면 팝업과 비슷합니다.

Google 및 Microsoft와 같은 일부 공급업체는 이메일 및 소셜 ID 공급업체 역할도 합니다. 이메일 공급업체는 호스팅된 이메일 도메인과 관련된 모든 주소에 대한 권한이 있는 것으로 간주됩니다. 즉, 동일한 공급업체에서 호스팅하는 이메일 주소로 로그인하는 사용자에게는 이 오류가 발생하지 않습니다(예: @gmail.com 이메일을 사용하여 Google로 또는 @live.com 또는 @outlook.com 이메일을 사용하여 Microsoft로 로그인).

수동으로 계정 병합

사용자가 동일한 공급업체를 사용하여 다른 사용자 계정에 이미 연결된 사용자 인증 정보로 로그인을 시도하면 클라이언트 SDK에 내장된 계정 연결 메서드가 실패합니다. 이 경우에는 계정을 수동으로 병합한 다음 두 번째 계정을 삭제해야 합니다. 예를 들면 다음과 같습니다.

자바스크립트

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

사용자 계정에서 공급업체를 연결 해제할 수 있습니다. 사용자는 더 이상 해당 공급업체로 인증할 수 없습니다.

공급업체 연결을 해제하려면 공급업체 ID를 사용자의 unlink() 메서드에 전달합니다. providerData 속성에서 ID를 가져올 수 있습니다.

자바스크립트

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

다음 단계