在 Apple 平台上使用電話號碼驗證 Firebase

您可以使用 Firebase 驗證功能,透過傳送簡訊到使用者的手機登入使用者。使用者使用簡訊中的一次性代碼登入。

如要在應用程式中加入電話號碼登入,最簡單的方法就是使用 FirebaseUI,其中包含一個導入電話號碼登入流程的置入式小工具,以及密碼與聯合登入。本文說明如何使用 Firebase SDK 導入電話號碼登入流程。

事前準備

  1. 如果您尚未將應用程式連結至 Firebase 專案,請透過 Firebase 控制台進行。
  2. 使用 Swift Package Manager 安裝及管理 Firebase 依附元件。

    1. 在 Xcode 中保持開啟應用程式專案,然後依序點選「File」>「Add Packages」
    2. 在系統提示時,新增 Firebase Apple 平台 SDK 存放區:
    3.   https://github.com/firebase/firebase-ios-sdk.git
    4. 選擇 Firebase 驗證資料庫。
    5. 在目標建構設定的「Other Linker Flags」部分中新增 -ObjC 標記。
    6. 完成後,Xcode 會自動開始在背景解析並下載依附元件。

安全疑慮

僅使用電話號碼進行驗證,但比其他可用的方法更安全,因為使用者可以在使用者之間輕鬆轉移電話號碼。此外,如果裝置上有多個使用者設定檔,任何可接收簡訊的使用者,都能使用裝置的電話號碼登入帳戶。

如果您在應用程式中使用以電話號碼為基礎的登入功能,建議您除了提供更安全的登入方式之外,也應向使用者說明使用電話號碼登入機制在安全性方面的保障。

為 Firebase 專案啟用電話號碼登入功能

如要透過簡訊登入使用者,您必須先為 Firebase 專案啟用電話號碼登入方式:

  1. Firebase 控制台開啟「驗證」專區。
  2. 在「Sign-in Method」(登入方式) 頁面中,啟用「Phone Number」(電話號碼) 登入方式。

Firebase 的電話號碼登入要求配額夠高,因此大多數應用程式不會受到影響。不過,如果您需要透過電話驗證來登入大量使用者,則可能需要升級定價方案。請參閱定價頁面。

啟用應用程式驗證功能

如要使用電話號碼驗證功能,Firebase 必須能夠驗證電話號碼登入要求是否確實來自您的應用程式。Firebase 驗證的方法有兩種:

  • 靜音 APN 通知:當您首次在裝置上以電話號碼登入使用者時,Firebase 驗證會以無訊息的推播通知將權杖傳送至裝置。如果您的應用程式已成功收到 Firebase 的通知,就能使用電話號碼登入繼續進行。

    如果是 iOS 8.0 以上版本,則靜音通知不需要使用者明確同意,因此不受使用者拒絕在應用程式中接收 APN 通知的影響。因此,實作 Firebase 電話號碼驗證時,應用程式不需要求使用者權限即可接收推播通知。

  • reCAPTCHA 驗證:如果使用者無法傳送或接收無訊息推播通知,例如使用者已停用應用程式的背景重新整理功能,或在 iOS 模擬工具上測試應用程式,Firebase 驗證就會使用 reCAPTCHA 驗證來完成手機登入流程。使用者通常不必解決任何問題,就能輕鬆完成 reCAPTCHA 驗證問題。

在正確設定無聲推播通知後,只有極少數的使用者才會遇到 reCAPTCHA 流程。儘管如此,無論是否提供靜音推播通知,都應確保使用者登入電話號碼後能正常運作。

開始接收靜音通知

如何啟用與 Firebase 驗證搭配使用的 APN 通知:

  1. 在 Xcode 中,為專案 啟用推播通知
  2. 將 APN 驗證金鑰上傳至 Firebase。如果您還沒有 APN 驗證金鑰,請務必前往 Apple Developer Member Center 建立 APN 驗證金鑰。

    1. 在 Firebase 控制台的專案中,依序選取齒輪圖示 >「專案設定」,然後選取「雲端通訊」分頁標籤。

    2. 在「iOS app configuration」下方的「APNs 驗證金鑰」中,按一下「上傳」按鈕。

    3. 瀏覽至您儲存金鑰的位置,選取金鑰,然後按一下 [Open] (開啟)。加入金鑰金鑰 ID (可於 Apple Developer Member Center 中找到),然後按一下「上傳」

    如果您已有 APN 憑證,可以改為上傳憑證。

設定 reCAPTCHA 驗證

如要啟用 Firebase SDK 進行 reCAPTCHA 驗證,請按照下列步驟操作:

  1. 在 Xcode 專案中新增自訂網址配置:
    1. 開啟專案設定:在左側樹狀檢視中,按兩下專案名稱。從「TARGETS」(目標) 部分選取您的應用程式,選取「Info」(資訊) 分頁標籤,然後展開「URL Types」(網址類型) 部分。
    2. 按一下「+」按鈕,然後新增您的編碼應用程式 ID 做為網址配置。前往 Firebase 控制台的「一般設定」頁面,即可在 iOS 應用程式專區中找到經過編碼的應用程式 ID。請將其他欄位留白。

      設定完成後,設定看起來應類似下列內容 (但會使用您的應用程式專屬值):

      Xcode 自訂網址配置設定介面的螢幕擷取畫面
  2. 選用:如果您想自訂向使用者顯示 reCAPTCHA 時應用程式顯示 SFSafariViewController 的方式,請建立符合 AuthUIDelegate 通訊協定的自訂類別,並傳遞至 verifyPhoneNumber(_:uiDelegate:completion:)

將驗證碼傳送至使用者的手機

如要啟動電話號碼登入程序,請向使用者顯示提示,提示他們提供電話號碼,然後呼叫 verifyPhoneNumber(_:uiDelegate:completion:) 以要求 Firebase 透過簡訊將驗證碼傳送至使用者的手機:

  1. 取得使用者的電話號碼。

    相關法律要求各有不同,但您應告知使用者,讓他們使用手機登入時,可能會收到驗證簡訊和標準費率的簡訊。

  2. 呼叫 verifyPhoneNumber(_:uiDelegate:completion:) 並傳送至使用者的電話號碼。

    Swift

    PhoneAuthProvider.provider()
      .verifyPhoneNumber(phoneNumber, uiDelegate: nil) { verificationID, error in
          if let error = error {
            self.showMessagePrompt(error.localizedDescription)
            return
          }
          // Sign in using the verificationID and the code sent to the user
          // ...
      }

    Objective-C

    [[FIRPhoneAuthProvider provider] verifyPhoneNumber:userInput
                                            UIDelegate:nil
                                            completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) {
      if (error) {
        [self showMessagePrompt:error.localizedDescription];
        return;
      }
      // Sign in using the verificationID and the code sent to the user
      // ...
    }];

    verifyPhoneNumber 方法會重新發送:如果多次呼叫 (例如在檢視區塊的 onAppear 方法中),verifyPhoneNumber 方法不會傳送第二則簡訊,除非原始要求逾時。

    當你呼叫 verifyPhoneNumber(_:uiDelegate:completion:) 時,Firebase 會傳送無訊息推送通知至您的應用程式,或是發出 reCAPTCHA 驗證問題給使用者。您的應用程式收到通知或使用者完成 reCAPTCHA 驗證問題後,Firebase 會將含有驗證碼的簡訊傳送至指定的電話號碼,並將驗證 ID 傳遞至完成函式。您需要驗證碼和驗證 ID,才能登入使用者。

    您也可以透過驗證執行個體上的 languageCode 屬性指定驗證語言,以將 Firebase 傳送的簡訊本地化。

    Swift

     // Change language code to french.
     Auth.auth().languageCode = "fr";
    

    Objective-C

     // Change language code to french.
     [FIRAuth auth].languageCode = @"fr";
    
  3. 儲存驗證 ID,並在應用程式載入時還原驗證 ID。如此一來,即使應用程式在使用者完成登入流程前 (例如切換至簡訊應用程式) 前遭到終止,您還能確保自己仍具有有效的驗證 ID。

    您可以視需求保留驗證 ID,方法很簡單,只要使用 NSUserDefaults 物件儲存驗證 ID:

    Swift

    UserDefaults.standard.set(verificationID, forKey: "authVerificationID")
    

    Objective-C

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:verificationID forKey:@"authVerificationID"];
    

    然後,您可以還原已儲存的值:

    Swift

    let verificationID = UserDefaults.standard.string(forKey: "authVerificationID")
    

    Objective-C

    NSString *verificationID = [defaults stringForKey:@"authVerificationID"];
    

如果呼叫 verifyPhoneNumber(_:uiDelegate:completion:) 成功,您可以在使用者透過簡訊收到驗證碼時,提示使用者輸入驗證碼。

透過驗證碼登入使用者

使用者透過簡訊將驗證碼提供給應用程式後,請透過驗證碼和驗證 ID 建立 FIRPhoneAuthCredential 物件,然後將該物件傳遞至 signInWithCredential:completion:,藉此登入使用者。

  1. 向使用者取得驗證碼。
  2. 透過驗證碼和驗證 ID 建立 FIRPhoneAuthCredential 物件。

    Swift

    let credential = PhoneAuthProvider.provider().credential(
      withVerificationID: verificationID,
      verificationCode: verificationCode
    )

    Objective-C

    FIRAuthCredential *credential = [[FIRPhoneAuthProvider provider]
        credentialWithVerificationID:verificationID
                    verificationCode:userInput];
  3. 使用 FIRPhoneAuthCredential 物件登入使用者身分:

    Swift

    Auth.auth().signIn(with: credential) { authResult, error in
        if let error = error {
          let authError = error as NSError
          if isMFAEnabled, authError.code == AuthErrorCode.secondFactorRequired.rawValue {
            // The user is a multi-factor user. Second factor challenge is required.
            let resolver = authError
              .userInfo[AuthErrorUserInfoMultiFactorResolverKey] as! MultiFactorResolver
            var displayNameString = ""
            for tmpFactorInfo in resolver.hints {
              displayNameString += tmpFactorInfo.displayName ?? ""
              displayNameString += " "
            }
            self.showTextInputPrompt(
              withMessage: "Select factor to sign in\n\(displayNameString)",
              completionBlock: { userPressedOK, displayName in
                var selectedHint: PhoneMultiFactorInfo?
                for tmpFactorInfo in resolver.hints {
                  if displayName == tmpFactorInfo.displayName {
                    selectedHint = tmpFactorInfo as? PhoneMultiFactorInfo
                  }
                }
                PhoneAuthProvider.provider()
                  .verifyPhoneNumber(with: selectedHint!, uiDelegate: nil,
                                     multiFactorSession: resolver
                                       .session) { verificationID, error in
                    if error != nil {
                      print(
                        "Multi factor start sign in failed. Error: \(error.debugDescription)"
                      )
                    } else {
                      self.showTextInputPrompt(
                        withMessage: "Verification code for \(selectedHint?.displayName ?? "")",
                        completionBlock: { userPressedOK, verificationCode in
                          let credential: PhoneAuthCredential? = PhoneAuthProvider.provider()
                            .credential(withVerificationID: verificationID!,
                                        verificationCode: verificationCode!)
                          let assertion: MultiFactorAssertion? = PhoneMultiFactorGenerator
                            .assertion(with: credential!)
                          resolver.resolveSignIn(with: assertion!) { authResult, error in
                            if error != nil {
                              print(
                                "Multi factor finanlize sign in failed. Error: \(error.debugDescription)"
                              )
                            } else {
                              self.navigationController?.popViewController(animated: true)
                            }
                          }
                        }
                      )
                    }
                  }
              }
            )
          } else {
            self.showMessagePrompt(error.localizedDescription)
            return
          }
          // ...
          return
        }
        // User is signed in
        // ...
    }

    Objective-C

    [[FIRAuth auth] signInWithCredential:credential
                              completion:^(FIRAuthDataResult * _Nullable authResult,
                                           NSError * _Nullable error) {
        if (isMFAEnabled && error && error.code == FIRAuthErrorCodeSecondFactorRequired) {
          FIRMultiFactorResolver *resolver = error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey];
          NSMutableString *displayNameString = [NSMutableString string];
          for (FIRMultiFactorInfo *tmpFactorInfo in resolver.hints) {
            [displayNameString appendString:tmpFactorInfo.displayName];
            [displayNameString appendString:@" "];
          }
          [self showTextInputPromptWithMessage:[NSString stringWithFormat:@"Select factor to sign in\n%@", displayNameString]
                               completionBlock:^(BOOL userPressedOK, NSString *_Nullable displayName) {
           FIRPhoneMultiFactorInfo* selectedHint;
           for (FIRMultiFactorInfo *tmpFactorInfo in resolver.hints) {
             if ([displayName isEqualToString:tmpFactorInfo.displayName]) {
               selectedHint = (FIRPhoneMultiFactorInfo *)tmpFactorInfo;
             }
           }
           [FIRPhoneAuthProvider.provider
            verifyPhoneNumberWithMultiFactorInfo:selectedHint
            UIDelegate:nil
            multiFactorSession:resolver.session
            completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) {
              if (error) {
                [self showMessagePrompt:error.localizedDescription];
              } else {
                [self showTextInputPromptWithMessage:[NSString stringWithFormat:@"Verification code for %@", selectedHint.displayName]
                                     completionBlock:^(BOOL userPressedOK, NSString *_Nullable verificationCode) {
                 FIRPhoneAuthCredential *credential =
                     [[FIRPhoneAuthProvider provider] credentialWithVerificationID:verificationID
                                                                  verificationCode:verificationCode];
                 FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
                 [resolver resolveSignInWithAssertion:assertion completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
                   if (error) {
                     [self showMessagePrompt:error.localizedDescription];
                   } else {
                     NSLog(@"Multi factor finanlize sign in succeeded.");
                   }
                 }];
               }];
              }
            }];
         }];
        }
      else if (error) {
        // ...
        return;
      }
      // User successfully signed in. Get user data from the FIRUser object
      if (authResult == nil) { return; }
      FIRUser *user = authResult.user;
      // ...
    }];

使用虛構的電話號碼進行測試

您可以透過 Firebase 控制台設定用於開發的虛構電話號碼。使用虛構的電話號碼進行測試有以下優點:

  • 測試電話號碼驗證,而不耗用您的使用配額。
  • 在不傳送實際簡訊的情況下,測試電話號碼的驗證方式。
  • 以相同的電話號碼連續執行測試,而不會受到限制。這種做法可以盡可能降低應用程式商店審查流程中遭到拒絕的風險。這樣一來,如果審查人員當初是以同一組電話號碼進行測試,他們就會使用同一組電話號碼進行測試。
  • 無須額外費心,即可在開發環境中輕鬆進行測試,例如可以在 iOS 模擬器中進行開發,或是在沒有 Google Play 服務的 Android 模擬器中進行開發。
  • 編寫整合測試時,不會因實際電話號碼在正式環境中執行安全性檢查而遭到封鎖。

虛構電話號碼必須符合下列規定:

  1. 請務必使用虛構的電話號碼,而且尚未取得。 Firebase 驗證無法將真人使用者目前使用的電話號碼設為測試號碼。其中一種選項是使用 555 組的號碼做為美國測試電話號碼,例如:+1 650-555-3434
  2. 電話號碼必須符合長度和其他限制的正確格式。不過,他們仍須完成與實際使用者電話號碼相同的驗證。
  3. 您最多可以新增 10 組開發用電話號碼。
  4. 請使用難以猜到及變動的測試電話號碼/代碼。

建立虛構的電話號碼和驗證碼

  1. Firebase 控制台開啟「驗證」專區。
  2. 在「登入方式」分頁中啟用電話服務供應商 (如果您尚未啟用的話)。
  3. 開啟「測試用電話號碼」選單。
  4. 提供要測試的電話號碼,例如 +1 650-555-3434
  5. 提供該特定號碼的 6 位數驗證碼,例如「654321」
  6. 新增數字。如果需要,您可以刪除電話號碼及其程式碼,只要將滑鼠遊標懸停在對應資料列上,再按一下垃圾桶圖示即可。

手動測試

您可以直接開始在應用程式中使用虛構的電話號碼。這樣一來,您就能在開發階段執行手動測試,而不會遇到配額問題或節流問題。您也可以直接在未安裝 Google Play 服務的 iOS 模擬器或 Android 模擬器中進行測試。

如果提供虛構電話號碼並傳送驗證碼,系統不會傳送實際簡訊。您必須改為提供先前設定的驗證碼,才能完成登入程序。

登入完成後,系統會使用該電話號碼建立 Firebase 使用者。使用者和實際電話號碼使用者的行為和屬性相同,也能以相同方式存取即時資料庫/Cloud Firestore 和其他服務。在這個過程中,建立的 ID 權杖與實際電話號碼使用者的簽章相同。

如果想要進一步限制存取權,您也可以透過自訂聲明為這些使用者設定測試角色,藉此區分他們為假使用者。

整合測試

除了手動測試之外,Firebase 驗證也提供 API,協助您撰寫手機驗證測試的整合測試。這些 API 會停用網頁版 reCAPTCHA 要求,並在 iOS 中停用靜音推播通知,藉此停用應用程式驗證功能。如此一來,就能在這些流程中進行自動化測試,更輕鬆地實作。還可讓您測試 Android 上的即時驗證流程。

在 iOS 上,appVerificationDisabledForTesting 設定必須設為 TRUE,才能呼叫 verifyPhoneNumber。處理過程不需要任何 APN 權杖,或是在背景傳送無訊息的推播通知,方便您在模擬器中進行測試。這麼做也會停用 reCAPTCHA 備用流程。

請注意,如果停用應用程式驗證功能,就無法使用非虛構的電話號碼完成登入。這個 API 只能使用虛構的電話號碼。

Swift

let phoneNumber = "+16505554567"

// This test verification code is specified for the given test phone number in the developer console.
let testVerificationCode = "123456"

Auth.auth().settings.isAppVerificationDisabledForTesting = TRUE
PhoneAuthProvider.provider().verifyPhoneNumber(phoneNumber, uiDelegate:nil) {
                                                            verificationID, error in
    if (error) {
      // Handles error
      self.handleError(error)
      return
    }
    let credential = PhoneAuthProvider.provider().credential(withVerificationID: verificationID ?? "",
                                                               verificationCode: testVerificationCode)
    Auth.auth().signInAndRetrieveData(with: credential) { authData, error in
      if (error) {
        // Handles error
        self.handleError(error)
        return
      }
      _user = authData.user
    }];
}];

Objective-C

NSString *phoneNumber = @"+16505554567";

// This test verification code is specified for the given test phone number in the developer console.
NSString *testVerificationCode = @"123456";

[FIRAuth auth].settings.appVerificationDisabledForTesting = YES;
[[FIRPhoneAuthProvider provider] verifyPhoneNumber:phoneNumber
                                        completion:^(NSString *_Nullable verificationID,
                                                     NSError *_Nullable error) {
    if (error) {
      // Handles error
      [self handleError:error];
      return;
    }
    FIRAuthCredential *credential =
        [FIRPhoneAuthProvider credentialWithVerificationID:verificationID
                                          verificationCode:testVerificationCode];
    [FIRAuth auth] signInWithAndRetrieveDataWithCredential:credential
                                                completion:^(FIRUser *_Nullable user,
                                                             NSError *_Nullable error) {
      if (error) {
        // Handles error
        [self handleError:error];
        return;
      }
      _user = user;
    }];
}];

附錄:在不移位的情況下使用手機登入

Firebase 驗證會使用方法清除功能,自動取得應用程式的 APN 權杖,處理 Firebase 傳送至應用程式的無訊息推播通知,並在驗證期間自動攔截來自 reCAPTCHA 驗證頁面的自訂配置重新導向。

如果您不想使用清除功能,可以在應用程式的 Info.plist 檔案中加入 FirebaseAppDelegateProxyEnabled 標記,並將其設為 NO 以停用此功能。請注意,將此標記設為 NO 也會停用其他 Firebase 產品的滑動功能,包括 Firebase 雲端通訊。

如果停用滑動功能,就必須明確將 APN 裝置權杖、推播通知和自訂配置重新導向網址傳送至 Firebase 驗證。

如果您正在建構 SwiftUI 應用程式,您也必須明確將 APN 裝置權杖、推播通知和自訂配置重新導向網址傳送至 Firebase 驗證。

如要取得 APN 裝置權杖,請實作 application(_:didRegisterForRemoteNotificationsWithDeviceToken:) 方法,然後在該權杖中,將裝置權杖傳遞至 AuthsetAPNSToken(_:type:) 方法。

Swift

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
  // Pass device token to auth
  Auth.auth().setAPNSToken(deviceToken, type: .prod)

  // Further handling of the device token if needed by the app
  // ...
}

Objective-C

- (void)application:(UIApplication *)application
    didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
  // Pass device token to auth.
  [[FIRAuth auth] setAPNSToken:deviceToken type:FIRAuthAPNSTokenTypeProd];
  // Further handling of the device token if needed by the app.
}

如要處理推播通知,請在 application(_:didReceiveRemoteNotification:fetchCompletionHandler:): 方法中呼叫 AuthcanHandleNotification(_:) 方法,檢查是否有 Firebase 驗證相關通知。

Swift

func application(_ application: UIApplication,
    didReceiveRemoteNotification notification: [AnyHashable : Any],
    fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
  if Auth.auth().canHandleNotification(notification) {
    completionHandler(.noData)
    return
  }
  // This notification is not auth related; it should be handled separately.
}

Objective-C

- (void)application:(UIApplication *)application
    didReceiveRemoteNotification:(NSDictionary *)notification
          fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
  // Pass notification to auth and check if they can handle it.
  if ([[FIRAuth auth] canHandleNotification:notification]) {
    completionHandler(UIBackgroundFetchResultNoData);
    return;
  }
  // This notification is not auth related; it should be handled separately.
}

如要處理自訂配置重新導向網址,請實作 application(_:open:options:) 方法,並在其中將網址傳遞至 AuthcanHandleURL(_:) 方法。

Swift

func application(_ application: UIApplication, open url: URL,
    options: [UIApplicationOpenURLOptionsKey : Any]) -> Bool {
  if Auth.auth().canHandle(url) {
    return true
  }
  // URL not auth related; it should be handled separately.
}

Objective-C

- (BOOL)application:(UIApplication *)app
            openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {
  if ([[FIRAuth auth] canHandleURL:url]) {
    return YES;
  }
  // URL not auth related; it should be handled separately.
}

如果您使用 SwiftUI 或 UISceneDelegate,請實作 scene(_:openURLContexts:) 方法,並在這些方法中將網址傳遞至 AuthcanHandleURL(_:) 方法。

Swift

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
  for urlContext in URLContexts {
      let url = urlContext.url
      Auth.auth().canHandle(url)
  }
  // URL not auth related; it should be handled separately.
}

Objective-C

- (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts {
  for (UIOpenURLContext *urlContext in URLContexts) {
    [FIRAuth.auth canHandleURL:urlContext.url];
    // URL not auth related; it should be handled separately.
  }
}

後續步驟

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

  • 在應用程式中,您可以透過 User 物件取得使用者的基本個人資料。請參閱管理使用者

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

您可以將驗證供應商憑證連結至現有的使用者帳戶,讓使用者透過多個驗證服務提供者登入您的應用程式。

如要登出使用者,請呼叫 signOut:

Swift

let firebaseAuth = Auth.auth()
do {
  try firebaseAuth.signOut()
} catch let signOutError as NSError {
  print("Error signing out: %@", signOutError)
}

Objective-C

NSError *signOutError;
BOOL status = [[FIRAuth auth] signOut:&signOutError];
if (!status) {
  NSLog(@"Error signing out: %@", signOutError);
  return;
}

您可能也想要針對各種驗證錯誤加入錯誤處理程式碼。請參閱處理錯誤