簡體   English   中英

檢查Firebase Facebook用戶是否存在,而無需從匿名用戶創建用戶

[英]Check if Firebase Facebook user exists without creating a user starting from anonymous user

在Firebase中,我需要檢查Facebook用戶是否存在而不創建該用戶。 最初,用戶是匿名的,他們嘗試使用Facebook登錄。 如果Facebook帳戶尚未鏈接到我的系統中的用戶,我希望此操作失敗。 它不會鏈接到當前用戶,因為他們是匿名用戶,

如果我使用Auth.signInAndRetrieveDataWithCredential,則可能會出現“ auth / user-not-found ”錯誤,但是只是創建了用戶。 這是錯誤還是預期的?

let credential = firebase.auth.FacebookAuthProvider.credential(
        event.authResponse.accessToken)
    firebase.auth().signInAndRetrieveDataWithCredential(credential).then( (userCredential) => {
        let user = userCredential.user
        app.debug("DEBUG: Existing user signed in:"+user.uid)
        this.loginSuccess(user)
    }).catch( (err) => {
        app.error("ERROR re-signing in:"+err.code)
        $("#login_status_msg").text(err)
    })

如果我使用User.reauthenticateAndRetrieveDataWithCredential,則會收到錯誤“ auth / user-mismatch ”,這很有意義,因為用戶當前是匿名用戶。 但是,我期望如果憑據不存在,則可能會拋出“ auth / user-not-found”,但這不會發生。

我沒有找到一種方法來吸引我的匿名用戶,讓他們使用Facebook登錄,然后查看是否有另一個用戶已鏈接到該Facebook憑據,而無需創建該用戶(如果該用戶不存在)。

如果您想知道為什么? 我的情況是:系統允許匿名用戶

  1. 用戶登錄,然后通過在Facebook中注冊轉換為登錄用戶。
  2. 應用程式解除安裝
  3. 重新安裝應用
  4. 用戶啟動應用程序,最初是匿名用戶。
  5. 他們嘗試再次登錄Facebook。 此時,如果他們還沒有用戶,我想阻止他們創建用戶。 如果他們已經有一個用戶ID,則該代碼可以正常工作,並將其匿名帳戶ID更改為原始用戶ID很好。

我找到了解決方案! 實施起來並不難,但是看起來確實很hack。

因此我們知道,在使用signInAndRetrieveDataWithCredential(cred)進行Facebook登錄時, 即使該帳戶尚不存在 ,也會創建該帳戶 為了解決這個問題,我們需要確保處理以下三件事:

  1. 檢測帳戶是否為新帳戶
  2. 刪除由Firebase創建的當前帳戶
  3. 拋出錯誤以退出當前流程並返回到以前的任何位置。

我剛剛實現並測試了該解決方案,它看起來很棒:

// ... do your stuff to do fb login, get credential, etc:
const userInfo = await firebase.auth().signInAndRetrieveDataWithCredential(credential)

// userInfo includes a property to check if the account is new:
const isNewUser = _.get(userInfo, 'additionalUserInfo.isNewUser', true)

// FIRST, delete the account we just made.
// SECOND, throw an error (or otherwise escape the current context.
if (isNewUser) {
  firebase.auth().currentUser.delete()
  throw new Error('Couldn\'t find an existing account.')
}

// If the user already exists, just handle normal login
return userInfo.user

我這樣做的原因是為了確保用戶必須通過我的應用程序中的“創建帳戶流程”。 您的案例也很容易實現,如下所示:

let credential = firebase.auth.FacebookAuthProvider.credential(event.authResponse.accessToken)

firebase.auth().signInAndRetrieveDataWithCredential(credential)
  .then(userCredential => {
    const isNewUser = userCredential.additionalUserInfo.isNewUser
    if (isNewUser) {
      firebase.auth().currentUser.delete()
      // The following error will be handled in your catch statement
      throw new Error("Couldn't find an existing account.")
    }
    // Otherwise, handle login normally:
    const user = userCredential.user
    app.debug("DEBUG: Existing user signed in:"+user.uid)
    this.loginSuccess(user)
  }).catch( (err) => {
    app.error("ERROR re-signing in:"+err.code)
    $("#login_status_msg").text(err)
  })

您可以使用方法fetchSignInMethodsForEmail來檢查特定的電子郵件是否已經與特定的提供者相關聯。 這樣做,您將能夠檢查與您的用戶關聯的電子郵件的SighInMethods是否包含Facebook.com

我在下面的示例中向您展示了如何在應用程序中管理這種情況。 我在代碼上使用RxJavaWrapper,但是您將了解如何管理它的要點:

 RxFirebaseAuth.fetchSignInMethodsForEmail(authInstance, email)
                .flatMap { providerResult ->
                    if (!providerResult.signInMethods!!.contains(credential.provider)) {
                        return@flatMap Maybe.error<AuthResult>(ProviderNotLinkedException(credential.provider))
                    } else {
                        return@flatMap RxFirebaseAuth.signInWithCredential(authInstance, credential)
                    }
                }
                .subscribe({ authResult ->
                  //Manage success
                }, { error ->
                  //Manage error
                })
  • 首先,我檢查與用戶電子郵件關聯的提供者(您可以從提供者中檢索它)
  • 如果SignInMethods列表包含我的憑據提供程序,則拋出錯誤,如果不是,則調用我的signInWithCredential方法來創建用戶。
  • 繼續您的工作流程。

您可以使用linkAndRetrieveDataWithCredential

let credential = firebase.auth.FacebookAuthProvider.credential(
    event.authResponse.accessToken);
anonymousUser.linkAndRetrieveDataWithCredential(credential).then( (userCredential) => {
  // Firebase Auth only allows linking a credential if it is not
  // already linked to another account.
  // Now the anonymous account is upgraded to a permanent Facebook account.
}).catch( (err) => {
  // Check for code: auth/credential-already-in-use
  // When this error is returned, it means the credential is already
  // used by another account. 
})

為了解決此問題,而又不依賴於對linkAndRetrieveDataWithCredential的調用失敗並使用catch塊登錄已存在的用戶的問題,我linkAndRetrieveDataWithCredential是保存getCurrentAccessToken返回的userID字段。

const { userID } = data;
this.props.setFacebookId(userID); // saves the userID on the server

稍后我可以在下次用戶注冊Facebook時檢查該userID已經存在。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM