【问题标题】:Firestore + AngularFire - Link accountsFirestore + AngularFire - 链接帐户
【发布时间】:2018-10-16 13:19:09
【问题描述】:

我想为用户提供多种登录选项。现在谷歌和Facebook。 但是,当用户使用 Google 登录并随后尝试使用 Facebook 登录时,我收到错误消息:

已存在具有相同电子邮件地址但不同的帐户 登录凭据。使用与此关联的提供商登录 电子邮件地址。

所以我必须关联帐户。我没有找到任何相关文档,除了 this 没有多大帮助。我能在stackoverflow 上找到最好的信息,但由于某种原因,这对我来说还不够。 该解决方案处理signInWithPopup,这给了我这个错误:

“无法与弹窗建立连接。可能是 被浏览器屏蔽了。” 所以如果弹出窗口不起作用,我会调用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());
      }
    });
}

Popup 之后,您将进入then 并可以做任何事情。但重定向后,您会丢失您的信息。所以我把它存储在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);
  }
});

我在 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);
          });
      }
    }
  });
}

(这会产生另一个问题。我如何知道它是否是直接使用 Google 登录的用户的正常 signInWithRedirect。或者它是否是用户尝试使用 Facebook 登录并被提示后的重定向因为这个错误而用谷歌登录?我不想每次都合并凭据。但这是一个较小的问题。但我也很想在这里解决这个问题。)

但是signInWithCredential 给了我这个错误:

linkWithCredential 失败:第一个参数“credential”必须是有效的 凭证。

为此我找到了“解决方案”here

使用访问令牌调用signInWithCredential 时,您需要调用 它是这样的:

signInWithCredential(null, token);如果你在做 signInWithCredential(token) 那么你需要使用 ID Token 而不是 而不是访问令牌。

我尝试了两个版本,均未成功。第二个版本: this.afAuth.auth.signInWithCredential(firebase.auth.GoogleAuthProvider.credential((&lt;any&gt;this.credential).idToken)) 类型转换之所以存在,是因为我猜类型定义存在问题。

我尝试插入整个 credentials 对象,idToken 作为第一个参数,accessToken 作为第二个参数。但我总是得到: 第一个参数“凭据”必须是有效的凭据。

在我写这篇文章时,我突然想到这可能是linkWithCredential 的问题,而不是signInWithCredential 方法的问题。根据错误消息,这应该是显而易见的。我只是没有注意到它,因为谷歌搜索错误给了我那个解决方案。所以我迅速检查了authError 变量中的内容。有accessTokenproviderIdsignInMethod 方法。没有tokenId。所以我尝试发送accessToken 作为参数,而不是整个对象,但没有帮助。我尝试将其发送为null, accessToken。没有帮助。我试图找到linkWithCredential 方法的文档,但没有任何运气。所以我不知道它在期待什么。

我已经为此浪费了四天时间。这让我付出了很多心理健康的代价。有人可以帮帮我吗?

【问题讨论】:

    标签: angular firebase-authentication angularfire2


    【解决方案1】:

    您可以存储基础 OAuth 凭据(id 令牌或访问令牌):error.credential.idTokenerror.credential.accessToken 及其提供者 ID error.credential.providerId。返回页面后,您可以重新初始化凭证,例如:firebase.auth.FacebookAuthProvider.credential(accessToken)。使用 Google 成功重定向登录后,链接该凭据

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-15
      • 1970-01-01
      • 2018-04-30
      相关资源
      最近更新 更多