使用 Apple 和 Unity 進行驗證

您可根據 Firebase SDK 執行端對端 OAuth 2.0 登入流程,讓使用者以 Apple ID 向 Firebase 進行驗證。

事前準備

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

加入 Apple Developer Program

只有 Apple Developer Program 成員才能設定「使用 Apple 登入」。

設定「使用 Apple 登入」功能

您必須在 Firebase 專案中啟用 Apple 登入功能,並完成相關設定。Apple Developer 的設定會因 Android 和 Apple 平台而異。請先按照 iOS+ 和/或 Android 指南的「設定使用 Apple 登入」一節的說明操作。

啟用 Apple 做為登入服務供應商

  1. Firebase 控制台開啟「驗證」專區。在「登入方式」分頁中啟用「Apple」供應商。
  2. 調整 Apple 登入供應商設定:
    1. 如果只部署 Apple 平台的應用程式,請將「服務 ID」、「Apple 團隊 ID」、「私密金鑰」和「金鑰 ID」欄位留空。
    2. 如需 Android 裝置的支援:
      1. 將 Firebase 新增至您的 Android 專案。在 Firebase 控制台中設定應用程式時,請務必註冊應用程式的 SHA-1 簽名。
      2. Firebase 控制台開啟「驗證」專區。在「登入方式」分頁中,啟用「Apple」供應商。指定您在上一節建立的服務 ID。另外,請在 OAuth 代碼流程設定專區中,指定您在上一節建立的 Apple Team 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 登入 Nonce 和權杖產生作業,例如 Unity 的「使用 Apple Asset Storage 套件」。您可能需要修改程式碼,將產生的隨機 Nonce 字串填充為原始字串狀態,以便用於 Firebase 作業 (也就是在建立 Nonce 的 SHA256 摘要形式之前,先儲存該字串的副本)。

  2. 使用產生的權杖字串和原始 Nonce 建構 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 驗證您的使用者。

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

  1. 使用適用於 Apple 的提供者 ID 設定的 FederatedOAuthProviderData 執行個體。

    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. 使用驗證提供者物件進行 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 記事登入

不同於 Firebase 驗證支援的其他供應商,Apple 不提供相片網址。

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

Apple 只會在使用者首次登入時,與應用程式分享使用者資訊,例如顯示名稱。通常 Firebase 會在使用者首次使用 Apple 登入時儲存顯示名稱,您可以前往 auth.CurrentUser.DisplayName 取得這個名稱。不過,如果您先前曾透過 Apple 讓使用者在不使用 Firebase 的情況下登入應用程式,Apple 將不會提供 Firebase 使用者的顯示名稱。

後續步驟

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

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

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