使用 Apple 和 Unity 進行驗證

您可以使用 Firebase SDK 執行端對端 OAuth 2.0 登入流程,讓使用者透過 Apple ID 向 Firebase 驗證身分。

事前準備

如要使用 Apple 登入使用者,請先在 Apple 開發人員網站上設定「透過 Apple 登入」,然後為 Firebase 專案啟用 Apple 做為登入供應商。

加入 Apple 開發人員計畫

只有 Apple 開發人員計畫的成員可以設定「使用 Apple 帳戶登入」。

設定「使用 Apple 登入」功能

您必須在 Firebase 專案中啟用 Apple 登入功能,並正確設定。Android 和 Apple 平台的 Apple Developer 設定有所不同。 請先按照 iOS+ 和/或 Android 指南的「設定使用 Apple 登入」一節操作,再繼續進行後續步驟。

啟用 Apple 做為登入供應商

  1. Firebase 控制台中,依序前往「安全性」>「驗證」
  2. 在「登入方式」分頁中,啟用「Apple」登入供應商。
  3. 設定 Apple 登入供應商設定:
    • Apple:如果只在 Apple 平台上部署應用程式,可以將服務 ID、Apple Team ID、私密金鑰和金鑰 ID 欄位留空。
    • Android:完成下列步驟,支援 Android 裝置:
      1. 將 Firebase 新增至 Android 專案
      2. 指定應用程式的 SHA-1 指紋 (如果尚未指定)。
        1. Firebase 控制台中,依序前往 「設定」 > 「一般」分頁標籤
        2. 向下捲動至「您的應用程式」資訊卡,選取您的 Android 應用程式,然後在「SHA 憑證指紋」欄位中新增 SHA-1 指紋。

        如要瞭解如何取得應用程式的 SHA 指紋,請參閱「驗證用戶端」一文。

      3. 設定 Apple 登入提供者設定:
        1. Firebase 控制台中,依序前往「安全性」 > 「驗證」
        2. 在「登入方式」分頁中,按一下「Apple」登入供應商。
        3. 指定您在上一節建立的服務 ID。此外,在 OAuth 程式碼流程設定部分,請指定 Apple 團隊 ID,以及您在上一個部分建立的私密金鑰和金鑰 ID。

遵守 Apple 去識別化資料規定

「使用 Apple 登入」可讓使用者在登入時選擇匿名處理資料,包括電子郵件地址。選擇這個選項的使用者會取得網域為 privaterelay.appleid.com 的電子郵件地址。在應用程式中使用「使用 Apple 登入」時,您必須遵守 Apple 針對這些匿名 Apple ID 制定的任何適用開發人員政策或條款。

包括在將任何直接識別個人資訊與匿名 Apple ID 建立關聯前,取得所有必要的使用者同意聲明。使用 Firebase 驗證時,這可能包括下列動作:

  • 將電子郵件地址連結至匿名 Apple ID,或反向操作。
  • 將電話號碼連結至匿名 Apple ID,或反向操作
  • 將非匿名社群憑證 (Facebook、Google 等) 連結至匿名 Apple ID,反之亦然。

請注意,這份清單中僅列出部分示例。請參閱開發人員帳戶「會員資格」部分的《Apple 開發人員計畫授權協議》,確認應用程式符合 Apple 的規定。

存取 Firebase.Auth.FirebaseAuth 類別

FirebaseAuth 類別是所有 API 呼叫的閘道。 可透過 FirebaseAuth.DefaultInstance 存取。
Firebase.Auth.FirebaseAuth auth = Firebase.Auth.FirebaseAuth.DefaultInstance;

使用 Firebase SDK 處理登入流程

「使用 Apple 帳戶登入」的程序會因 Apple 和 Android 平台而異。

在 Apple 平台上

  1. 安裝第三方外掛程式,處理 Apple 登入隨機值和權杖產生作業,例如 Unity 的「Sign In With Apple Asset Storage Package」(使用 Apple 帳戶登入資產儲存套件)。您可能需要變更程式碼,以原始字串狀態導入產生的隨機 Nonce 字串,供 Firebase 作業使用 (也就是在建立 Nonce 的 SHA256 摘要形式之前,先儲存副本)。

  2. 使用產生的權杖字串和原始隨機值建構 Firebase 憑證,然後登入 Firebase。

    Firebase.Auth.Credential credential =
        Firebase.Auth.OAuthProvider.GetCredential("apple.com", appleIdToken, rawNonce, null);
    auth.SignInAndRetrieveDataWithCredentialAsync(credential).ContinueWith(task => {
      if (task.IsCanceled) {
        Debug.LogError("SignInAndRetrieveDataWithCredentialAsync was canceled.");
        return;
      }
      if (task.IsFaulted) {
        Debug.LogError("SignInAndRetrieveDataWithCredentialAsync encountered an error: " + task.Exception);
        return;
      }
    
      Firebase.Auth.AuthResult result = task.Result;
      Debug.LogFormat("User signed in successfully: {0} ({1})",
          result.User.DisplayName, result.User.UserId);
    });

  3. 您也可以將相同模式用於 ReauthenticateAsync,以便為需要最近登入的敏感作業擷取最新憑證。詳情請參閱「管理使用者」。

  4. 在 Apple 平台上使用「透過 Apple 登入」功能連結時,您可能會遇到錯誤,指出現有的 Firebase 帳戶已連結至 Apple 帳戶。發生這種情況時,系統會擲回 Firebase.Auth.FirebaseAccountLinkException,而非標準的 Firebase.FirebaseException。在這種情況下,例外狀況包含 UserInfo.UpdatedCredential 屬性,如果有效,可用於透過 FirebaseAuth.SignInAndRetrieveDataWithCredentialAsync 登入已連結 Apple 的使用者。更新後的憑證可避免在登入作業中,使用 Nonce 產生新的 Apple 登入權杖。

    auth.CurrentUser.LinkWithCredentialAsync(
      Firebase.Auth.OAuthProvider.GetCredential("apple.com", idToken, rawNonce, null))
        .ContinueWithOnMainThread( task => {
          if (task.IsCompletedSuccessfully) {
            // Link Success
          } else {
            if (task.Exception != null) {
              foreach (Exception exception in task.Exception.Flatten().InnerExceptions) {
                Firebase.Auth.FirebaseAccountLinkException firebaseEx =
                  exception as Firebase.Auth.FirebaseAccountLinkException;
                if (firebaseEx != null && firebaseEx.UserInfo.UpdatedCredential.IsValid()) {
                  // Attempt to sign in with the updated credential.
                  auth.SignInAndRetrieveDataWithCredentialAsync(firebaseEx.UserInfo.UpdatedCredential).
                    ContinueWithOnMainThread( authResultTask => {
                      // Handle Auth result.
                    });
                } else {
                  Debug.Log("Link with Apple failed:" + firebaseEx );
                }
              } // end for loop
            }
          }
        });

Android 版

在 Android 上,請使用 Firebase SDK 將網頁型一般 OAuth 登入服務整合至應用程式,以執行端對端登入流程,藉此透過 Firebase 驗證使用者。

如要使用 Firebase SDK 處理登入流程,請按照下列步驟操作:

  1. 建構 FederatedOAuthProviderData 的執行個體,並設定適用於 Apple 的提供者 ID。

    Firebase.Auth.FederatedOAuthProviderData providerData =
      new Firebase.Auth.FederatedOAuthProviderData();
    
    providerData.ProviderId = "apple.com";
    
  2. 選用:指定要向驗證供應商要求,但預設範圍以外的其他 OAuth 2.0 範圍。

    providerData.Scopes = new List<string>();
    providerData.Scopes.Add("email");
    providerData.Scopes.Add("name");
    
  3. 選用:如要以英文以外的語言顯示 Apple 登入畫面,請設定 locale 參數。如需支援的語言代碼,請參閱「使用 Apple 登入」文件。

    providerData.CustomParameters = new Dictionary<string,string>;
    
    // Localize to French.
    providerData.CustomParameters.Add("language", "fr");
    
  4. 設定供應商資料後,請使用該資料建立 FederatedOAuthProvider。

    // Construct a FederatedOAuthProvider for use in Auth methods.
    Firebase.Auth.FederatedOAuthProvider provider =
      new Firebase.Auth.FederatedOAuthProvider();
    provider.SetProviderData(providerData);
    
  5. 使用 Auth 提供者物件向 Firebase 進行驗證。請注意,與其他 FirebaseAuth 作業不同,這項作業會彈出網頁檢視畫面,讓使用者輸入憑證,藉此控管您的 UI。

    如要啟動登入流程,請呼叫 signInWithProvider

    auth.SignInWithProviderAsync(provider).ContinueOnMainThread(task => {
        if (task.IsCanceled) {
            Debug.LogError("SignInWithProviderAsync was canceled.");
            return;
        }
        if (task.IsFaulted) {
            Debug.LogError("SignInWithProviderAsync encountered an error: " +
              task.Exception);
            return;
        }
    
        Firebase.Auth.AuthResult authResult = task.Result;
        Firebase.Auth.FirebaseUser user = authResult.User;
        Debug.LogFormat("User signed in successfully: {0} ({1})",
            user.DisplayName, user.UserId);
    });
    
  6. 相同的模式可與 ReauthenticateWithProvider 搭配使用,以便擷取需要最近登入的敏感作業的新憑證。

    user.ReauthenticateWithProviderAsync(provider).ContinueOnMainThread(task => {
        if (task.IsCanceled) {
            Debug.LogError("ReauthenticateWithProviderAsync was canceled.");
            return;
        }
        if (task.IsFaulted) {
            Debug.LogError(
            "ReauthenticateWithProviderAsync encountered an error: " +
                task.Exception);
            return;
        }
    
        Firebase.Auth.AuthResult authResult = task.Result;
        Firebase.Auth.FirebaseUser user = authResult.User;
        Debug.LogFormat("User reauthenticated successfully: {0} ({1})",
            user.DisplayName, user.UserId);
    });
    
  7. 此外,您可以使用 LinkWithCredentialAsync() 將不同的身分識別提供者連結至現有帳戶。

    請注意,Apple 規定您必須先取得使用者明確同意,才能將他們的 Apple 帳戶連結至其他資料。

    舉例來說,如要將 Facebook 帳戶連結至目前的 Firebase 帳戶,請使用您透過登入 Facebook 取得的存取權杖:

    // Initialize a Facebook credential with a Facebook access token.
    
    Firebase.Auth.Credential credential =
        Firebase.Auth.FacebookAuthProvider.GetCredential(facebook_token);
    
    // Assuming the current user is an Apple user linking a Facebook provider.
    user.LinkWithCredentialAsync(credential)
        .ContinueWithOnMainThread( task => {
          if (task.IsCanceled) {
              Debug.LogError("LinkWithCredentialAsync was canceled.");
              return;
          }
          if (task.IsFaulted) {
            Debug.LogError("LinkWithCredentialAsync encountered an error: "
                           + task.Exception);
              return;
          }
    
          Firebase.Auth.AuthResult result = task.Result;
          Firebase.Auth.FirebaseUser user = result.User;
          Debug.LogFormat("User linked successfully: {0} ({1})",
              user.DisplayName, user.UserId);
        });
    

使用 Apple Notes 登入

與 Firebase Auth 支援的其他供應商不同,Apple 不會提供相片網址。

此外,如果使用者選擇不與應用程式分享電子郵件地址,Apple 會為該使用者提供專屬電子郵件地址 (格式為 xyz@privaterelay.appleid.com),並與您的應用程式分享。如果您已設定私人電子郵件轉發服務,Apple 會將傳送至匿名地址的電子郵件轉寄至使用者的實際電子郵件地址。

Apple 只會在使用者首次登入時,與應用程式分享顯示名稱等使用者資訊。通常,Firebase 會在使用者首次透過 Apple 登入時儲存顯示名稱,您可以透過 auth.CurrentUser.DisplayName 取得該名稱。不過,如果您先前使用 Apple 登入應用程式,但沒有使用 Firebase,Apple 就不會提供使用者的顯示名稱給 Firebase。

後續步驟

使用者首次登入後,系統會建立新的使用者帳戶,並連結使用者登入時使用的憑證 (即使用者名稱和密碼、電話號碼或驗證供應商資訊)。這個新帳戶會儲存在 Firebase 專案中,可用於識別專案中每個應用程式的使用者,無論使用者登入方式為何。

在應用程式中,您可以從 Firebase.Auth.FirebaseUser 物件取得使用者的基本個人資料資訊。請參閱「管理使用者」。

在 Firebase 即時資料庫和 Cloud Storage 安全性規則中,您可以從 auth 變數取得登入使用者的專屬使用者 ID,並用來控管使用者可存取的資料。