在 Apple 平台上使用電子郵件連結向 Firebase 驗證

您可以使用 Firebase 驗證功能,向使用者傳送電子郵件 內含連結,只要按一下即可登入。在過程中,使用者的 電子郵件地址也會通過驗證

使用電子郵件登入有以下優點:

  • 簡化註冊和登入程序。
  • 降低在不同應用程式間重複使用密碼的風險,可能導致安全性降低 甚至是已選取的密碼
  • 能夠驗證使用者身分,同時驗證使用者身分 電子郵件地址的合法擁有者。
  • 使用者只需具備可存取的電子郵件帳戶即可登入。不具備 必須提供電話號碼或社群媒體帳戶。
  • 使用者不需提供 (或記得) 存取 密碼,對行動裝置來說可能很麻煩。
  • 先前以電子郵件 ID (密碼) 登入的現有使用者 或聯合) 的電子郵件,只要以電子郵件登入即可。舉例來說 使用者就算忘記密碼,仍然可以登入, 重設密碼。

事前準備

使用 Swift Package Manager 安裝及管理 Firebase 依附元件。

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

如要透過電子郵件連結登入使用者,您必須先啟用電子郵件服務供應商,並 以電子郵件登入 Firebase 專案:

  1. Firebase 控制台,開啟 驗證區段。
  2. 在「Sign in method」分頁中啟用「Email/Password」供應商。注意事項 必須啟用電子郵件/密碼登入功能才能使用電子郵件連結登入。
  3. 在同一部分中啟用「電子郵件連結 (無密碼登入)」登入功能 方法。
  4. 按一下 [儲存]

如要啟動驗證流程,請向使用者顯示 提示使用者提供電子郵件地址,然後撥打電話 sendSignInLink:要求 Firebase 傳送驗證連結至使用者的電子郵件。

  1. 建構 ActionCodeSettings 物件,該物件提供 Firebase 提供的 有關如何建立電子郵件連結的指示。設定下列欄位:

    • url:要嵌入的深層連結,以及要一併傳送的任何其他狀態。 請在 Firebase 控制台的 只要前往 [登入方式] 分頁即可找到 (「驗證」->「登入方式」)。
    • iOSBundleID 和 androidPackageName:登入連結時使用的應用程式 是透過 Android 或 Apple 裝置開啟。進一步瞭解如何 設定 Firebase Dynamic Links ,透過行動應用程式開啟電子郵件動作連結。
    • handleCodeInApp:設為 true。每次登入作業都必須 在 app 中完成與其他頻帶電子郵件動作的方式不同 (密碼) 重設和電子郵件驗證)。因為在流程結束時 使用者應可登入,且驗證狀態會保留在 應用程式
    • DynamicLinkDomain:定義多個自訂動態連結網域時 請指定要在透過連結開啟連結時使用的 指定行動應用程式 (例如 example.page.link)。否則, 系統會自動選取第一個網域。

    Swift

    let actionCodeSettings = ActionCodeSettings()
    actionCodeSettings.url = URL(string: "https://www.example.com")
    // The sign-in operation has to always be completed in the app.
    actionCodeSettings.handleCodeInApp = true
    actionCodeSettings.setIOSBundleID(Bundle.main.bundleIdentifier!)
    actionCodeSettings.setAndroidPackageName("com.example.android",
                                             installIfNotAvailable: false, minimumVersion: "12")
    

    Objective-C

    FIRActionCodeSettings *actionCodeSettings = [[FIRActionCodeSettings alloc] init];
    [actionCodeSettings setURL:[NSURL URLWithString:@"https://www.example.com"]];
    // The sign-in operation has to always be completed in the app.
    actionCodeSettings.handleCodeInApp = YES;
    [actionCodeSettings setIOSBundleID:[[NSBundle mainBundle] bundleIdentifier]];
    [actionCodeSettings setAndroidPackageName:@"com.example.android"
                        installIfNotAvailable:NO
                               minimumVersion:@"12"];
    

    如要進一步瞭解 ActionCodeSettings,請參閱 電子郵件動作中的通過狀態 專區。

  2. 要求使用者提供電子郵件地址。

  3. 傳送驗證連結至使用者的電子郵件,並儲存使用者的電子郵件 在使用者在同一部裝置上完成電子郵件地址登入程序。

    Swift

    Auth.auth().sendSignInLink(toEmail: email,
                               actionCodeSettings: actionCodeSettings) { error in
      // ...
        if let error = error {
          self.showMessagePrompt(error.localizedDescription)
          return
        }
        // The link was successfully sent. Inform the user.
        // Save the email locally so you don't need to ask the user for it again
        // if they open the link on the same device.
        UserDefaults.standard.set(email, forKey: "Email")
        self.showMessagePrompt("Check your email for link")
        // ...
    }
    

    Objective-C

    [[FIRAuth auth] sendSignInLinkToEmail:email
                       actionCodeSettings:actionCodeSettings
                               completion:^(NSError *_Nullable error) {
      // ...
        if (error) {
          [self showMessagePrompt:error.localizedDescription];
           return;
        }
        // The link was successfully sent. Inform the user.
        // Save the email locally so you don't need to ask the user for it again
        // if they open the link on the same device.
        [NSUserDefaults.standardUserDefaults setObject:email forKey:@"Email"];
        [self showMessagePrompt:@"Check your email for link"];
        // ...
    }];
    

安全疑慮

防止他人透過非預期使用者身分登入 非預期裝置;Firebase 驗證會要求使用者的電子郵件地址 所提供的密碼。為確保登入成功,這封電子郵件 位址必須與最初登入連結的收件地址相符。

當使用者以相同方式開啟登入連結時, 裝置存取連結時,系統會將其電子郵件地址儲存在本機, 傳送登入電子郵件。接著,使用這個地址完成流程。

登入完成後,系統會採用先前的任何未經驗證登入機制 ,且所有現有工作階段都會失效。 舉例來說,假設有人 電子郵件地址,系統會移除使用者的密碼,以免 以模擬人的身分,提出擁有權並建立了未經驗證的帳戶 使用相同的帳戶登入。

在 Apple 行動應用程式中完成登入程序

Firebase 驗證會使用 Firebase Dynamic Links 將電子郵件連結傳送至 使用行動裝置如要透過行動應用程式完成登入程序,應用程式 您必須設定成偵測傳入的應用程式連結,剖析 ,然後完成登入。

Firebase 驗證會使用 Firebase Dynamic Links 傳送 要用在行動應用程式中開啟的連結為了使用這份 功能,就需要在 Firebase 控制台中設定 Dynamic Links。

  1. 啟用 Firebase Dynamic Links:

    1. Firebase 控制台開啟「Dynamic Links」部分。
    2. 如果您尚未接受 Dynamic Links 條款並建立 Dynamic Links 網域,請立即採取相關行動。

      若您已建立 Dynamic Links 網域,請記下該網域。動態連結 網域通常如下所示:

      example.page.link

      將 Apple 或 Android 應用程式設為 攔截傳入連結。

  2. 設定 Apple 應用程式:

    1. 如果您打算從應用程式處理這些連結,請 您必須在 Firebase 控制台中指定軟體包 ID 專案設定。此外,App Store ID 和 Apple Developer 您也需要指定團隊 ID。
    2. 您也必須將電子郵件動作處理常式網域設為 應用程式功能的關聯網域。根據預設, 電子郵件動作處理常式是由如下列範例所示的網域代管:
      APP_ID.firebaseapp.com
    3. 如果您打算將應用程式發行到 iOS 8 以下版本, 您需要將軟體包 ID 設定為 網址。
    4. 詳情請參閱 取得 Apple 平台 Dynamic Links 操作說明

收到上述連結後,請確認該連結是用於電子郵件 連結驗證,並完成登入。

Swift

if Auth.auth().isSignIn(withEmailLink: link) {
        Auth.auth().signIn(withEmail: email, link: self.link) { user, error in
          // ...
        }
}

Objective-C

if ([[FIRAuth auth] isSignInWithEmailLink:link]) {
    [[FIRAuth auth] signInWithEmail:email
                               link:link
                         completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
      // ...
    }];
}

瞭解如何在 Android 中處理透過電子郵件連結登入的作業 請參閱 Android 指南

瞭解如何處理網頁中的電子郵件連結登入作業 請參閱網頁指南

您也可以將這種驗證方法連結至現有的使用者。例如: 使用者先前已透過其他供應商 (如電話號碼) 完成驗證。 可以在現有帳戶中新增這種登入方式。

差異如下:作業的後半部:

Swift

  let credential = EmailAuthCredential.credential(withEmail:email
                                                       link:link)
  Auth.auth().currentUser?.link(with: credential) { authData, error in
    if (error) {
      // And error occurred during linking.
      return
    }
    // The provider was successfully linked.
    // The phone user can now sign in with their phone number or email.
  }

Objective-C

  FIRAuthCredential *credential =
      [FIREmailAuthProvider credentialWithEmail:email link:link];
  [FIRAuth auth].currentUser
      linkWithCredential:credential
              completion:^(FIRAuthDataResult *_Nullable result,
                           NSError *_Nullable error) {
    if (error) {
      // And error occurred during linking.
      return;
    }
    // The provider was successfully linked.
    // The phone user can now sign in with their phone number or email.
  }];

在執行 機密作業

Swift

  let credential = EmailAuthProvider.credential(withEmail:email
                                                       link:link)
  Auth.auth().currentUser?.reauthenticate(with: credential) { authData, error in
    if (error) {
      // And error occurred during re-authentication.
      return
    }
    // The user was successfully re-authenticated.
  }

Objective-C

  FIRAuthCredential *credential =
      [FIREmailAuthCredential credentialWithEmail:email link:link];
  [FIRAuth auth].currentUser
      reauthenticateWithCredential:credential
                        completion:^(FIRAuthDataResult *_Nullable result,
                                     NSError *_Nullable error) {
    if (error) {
      // And error occurred during re-authentication
      return;
    }
    // The user was successfully re-authenticated.
  }];

不過,由於流程最終可能會發生在原始使用者的裝置上 未登入,可能無法完成這個流程。在此情況下,錯誤可能 才能強制使用者在相同裝置上開啟連結。只有部分通知 狀態,以提供作業類型相關資訊 和使用者 uid

如果您是在 2023 年 9 月 15 日當天或之後建立專案,請透過電子郵件列舉項目 系統會預設啟用保護措施。這項功能可以提高 專案的使用者帳戶,但將 fetchSignInMethodsForEmail() 停用 方法 (先前建議用來實作 ID 優先流程)。

雖然您可以為專案停用電子郵件列舉防護功能, 並建議不要這樣做

請參閱電子郵件列舉防護功能說明文件 ,掌握更多詳細資訊。

後續步驟

使用者首次登入後,系統會建立新的使用者帳戶 也就是使用者的名稱和密碼 號碼或驗證提供者資訊,也就是使用者登入時使用的網址。這項新功能 帳戶儲存為 Firebase 專案的一部分,可用來識別 即可限制使用者登入專案中的所有應用程式

  • 在您的應用程式中,您可以透過 User 物件。請參閱管理使用者

  • 在您的 Firebase 即時資料庫和 Cloud Storage 中 查看安全性規則即可 透過 auth 變數取得已登入使用者的不重複使用者 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;
}

我們也建議您新增錯誤處理程式碼,適用於完整的驗證範圍 發生錯誤。請參閱處理錯誤