您可以透過 Firebase Authentication 傳送內含連結的電子郵件,讓使用者點選連結登入帳戶。系統也會在過程中驗證使用者的電子郵件地址。
使用電子郵件登入有許多好處:
- 輕鬆註冊及登入。
- 降低在不同應用程式重複使用密碼的風險,即使密碼選得再好,重複使用仍可能導致安全性問題。
- 驗證使用者身分,同時確認使用者是電子郵件地址的合法擁有者。
- 使用者只要有可存取的電子郵件帳戶就能登入。無須擁有電話號碼或社群媒體帳戶。
- 使用者不必提供 (或記住) 密碼,即可安全登入,這在行動裝置上可能很麻煩。
- 如果現有使用者先前是透過電子郵件 ID (密碼或同盟) 登入,可以升級為僅使用電子郵件登入。舉例來說,使用者忘記密碼時,仍可登入帳戶,不必重設密碼。
事前準備
設定 Android 專案
如果您尚未將 Firebase 新增至 Android 專案,請先新增。
在模組 (應用程式層級) Gradle 檔案 (通常是
<project>/<app-module>/build.gradle.kts
或<project>/<app-module>/build.gradle
) 中,加入 Android 適用的 Firebase Authentication 程式庫依附元件。建議使用 Firebase Android BoM 控制程式庫版本。此外,您也必須在設定 Firebase Authentication 時,將 Google Play 服務 SDK 新增至應用程式。
dependencies { // Import the BoM for the Firebase platform implementation(platform("com.google.firebase:firebase-bom:34.0.0")) // Add the dependency for the Firebase Authentication library // When using the BoM, you don't specify versions in Firebase library dependencies implementation("com.google.firebase:firebase-auth")
// Also add the dependency for the Google Play services library and specify its version implementation("com.google.android.gms:play-services-auth:21.3.0") }只要使用 Firebase Android BoM,應用程式就會一律使用相容的 Firebase Android 程式庫版本。
(替代做法) 不使用 BoM 新增 Firebase 程式庫依附元件
如果選擇不使用 Firebase BoM,則必須在依附元件行中指定每個 Firebase 程式庫版本。
請注意,如果應用程式使用多個 Firebase 程式庫,強烈建議使用 BoM 管理程式庫版本,確保所有版本都相容。
dependencies { // Add the dependency for the Firebase Authentication library // When NOT using the BoM, you must specify versions in Firebase library dependencies implementation("com.google.firebase:firebase-auth:24.0.0")
// Also add the dependency for the Google Play services library and specify its version implementation("com.google.android.gms:play-services-auth:21.3.0") }
為 Firebase 專案啟用電子郵件連結登入功能
如要透過電子郵件連結登入使用者,請先為 Firebase 專案啟用電子郵件供應商和電子郵件連結登入方法:
- 在 Firebase 控制台中,開啟「Auth」(驗證) 部分。
- 在「登入方式」分頁中,啟用「電子郵件地址/密碼」供應商。請注意,如要使用電子郵件連結登入,必須先啟用電子郵件地址/密碼登入功能。
- 在同一個部分中,啟用「電子郵件連結 (不需要密碼即可登入)」登入方法。
- 按一下 [儲存]。
將驗證連結傳送至使用者的電子郵件地址
如要啟動驗證流程,請向使用者顯示介面,提示使用者提供電子郵件地址,然後呼叫 sendSignInLinkToEmail
,要求 Firebase 將驗證連結傳送至使用者的電子郵件地址。
建構 ActionCodeSettings 物件,向 Firebase 提供電子郵件連結的建構方式。設定下列欄位:
url
:要嵌入的深層連結,以及要一併傳遞的任何其他狀態。 連結的網域必須在 Firebase 主控台的授權網域清單中加入許可清單。如要查看這份清單,請前往「登入方式」分頁 (「驗證」->「登入方式」)。如果使用者裝置上未安裝應用程式,且無法安裝,系統會將使用者重新導向至這個網址。
androidPackageName
和iOSBundleId
:協助 Firebase Authentication 判斷是否應建立僅限網頁或行動裝置的連結,並在 Android 或 Apple 裝置上開啟。handleCodeInApp
:設為 true。與其他頻外電子郵件動作 (密碼重設和電子郵件驗證) 不同,登入作業一律須在應用程式中完成。這是因為在流程結束時,使用者應已登入,且應用程式會保留其 Auth 狀態。linkDomain
:為專案定義自訂 Hosting 連結網域時,請指定要使用哪個網域,讓連結由特定行動應用程式開啟。否則系統會自動選取預設網域 (例如 )。PROJECT_ID.firebaseapp.com
dynamicLinkDomain
:已淘汰。請勿指定此參數。
Kotlin
val actionCodeSettings = actionCodeSettings { // URL you want to redirect back to. The domain (www.example.com) for this // URL must be whitelisted in the Firebase Console. url = "https://www.example.com/finishSignUp?cartId=1234" // This must be true handleCodeInApp = true setIOSBundleId("com.example.ios") setAndroidPackageName( "com.example.android", true, // installIfNotAvailable "12", // minimumVersion ) }
Java
ActionCodeSettings actionCodeSettings = ActionCodeSettings.newBuilder() // URL you want to redirect back to. The domain (www.example.com) for this // URL must be whitelisted in the Firebase Console. .setUrl("https://www.example.com/finishSignUp?cartId=1234") // This must be true .setHandleCodeInApp(true) .setIOSBundleId("com.example.ios") .setAndroidPackageName( "com.example.android", true, /* installIfNotAvailable */ "12" /* minimumVersion */) .build();
如要進一步瞭解 ActionCodeSettings,請參閱「在電子郵件動作中傳遞狀態」一節。
詢問使用者的電子郵件地址。
將驗證連結傳送至使用者的電子郵件地址,並儲存該地址,以防使用者在同一部裝置上完成電子郵件登入程序。
Kotlin
Firebase.auth.sendSignInLinkToEmail(email, actionCodeSettings) .addOnCompleteListener { task -> if (task.isSuccessful) { Log.d(TAG, "Email sent.") } }
Java
FirebaseAuth auth = FirebaseAuth.getInstance(); auth.sendSignInLinkToEmail(email, actionCodeSettings) .addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { if (task.isSuccessful()) { Log.d(TAG, "Email sent."); } } });
使用電子郵件連結完成登入程序
安全疑慮
為避免登入連結遭人濫用,導致使用者登入錯誤帳戶或裝置,Firebase Authentication 會要求使用者在完成登入流程時提供電子郵件地址。如要順利登入,這個電子郵件地址必須與登入連結原始傳送的地址相符。
當您傳送登入電子郵件時,可以將使用者的電子郵件地址儲存在本機 (例如使用 SharedPreferences),簡化使用者在要求連結的同一部裝置上開啟登入連結時的流程。然後使用這個地址完成流程。請勿在重新導向網址參數中傳遞使用者的電子郵件地址,並重複使用該地址,否則可能會導致工作階段遭注入內容。
登入完成後,系統會從使用者移除任何先前未驗證的登入機制,並使現有工作階段失效。舉例來說,如果有人先前使用相同的電子郵件地址和密碼建立未經驗證的帳戶,系統會移除該使用者的密碼,防止冒用者聲稱擁有該帳戶並建立未經驗證的帳戶,然後使用未經驗證的電子郵件地址和密碼再次登入。
此外,請務必在正式環境中使用 HTTPS 網址,以免連結遭到中繼伺服器攔截。
在 Android 應用程式中完成登入程序
Firebase Authentication 會使用 Firebase Hosting 將電子郵件連結傳送至行動裝置。如要透過行動應用程式完成登入,應用程式必須設定為偵測傳入的應用程式連結、剖析基礎深層連結,然後完成登入。詳情請參閱 Android 應用程式連結說明文件。
設定 Firebase Hosting
Firebase Authentication 在建立及傳送要在行動應用程式中開啟的連結時,會使用 Firebase Hosting 網域。系統已為您設定預設 Firebase Hosting 網域。
設定 Firebase Hosting 網域:
在 Firebase 控制台中,開啟「Hosting」部分。
如要使用預設網域做為在行動應用程式中開啟的電子郵件連結,請前往預設網站,並記下預設Hosting網域。預設 Hosting 網域通常如下所示:
。PROJECT_ID.firebaseapp.com
設定應用程式來攔截傳入的連結時,會需要用到這個值。
如要使用自訂網域做為電子郵件連結,可以向 Firebase Hosting 註冊網域,並將該網域用於連結。
設定 Android 應用程式:
如要從 Android 應用程式處理這些連結,請在 Firebase 控制台專案設定中指定應用程式的套件名稱。此外,您也必須提供應用程式憑證的 SHA-1 和 SHA-256。
如要讓這些連結重新導向至特定活動,您需要在
AndroidManifest.xml
檔案中設定意圖篩選器。意圖篩選器應擷取您網域的電子郵件連結。在AndroidManifest.xml
中:<intent-filter android:autoVerify="true"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="https" android:host="<PROJECT_ID>.firebaseapp.com or your custom domain" android:pathPrefix="/__/auth/links" /> </intent-filter>
使用者開啟含有
/__/auth/links
路徑,以及您指定配置和主機的代管連結時,應用程式會啟動含有這個意圖篩選器的活動,以處理連結。
驗證連結並登入
收到如上所述的連結後,請確認該連結是用於電子郵件連結驗證,然後完成登入。
Kotlin
val auth = Firebase.auth val intent = intent val emailLink = intent.data.toString() // Confirm the link is a sign-in with email link. if (auth.isSignInWithEmailLink(emailLink)) { // Retrieve this from wherever you stored it val email = "someemail@domain.com" // The client SDK will parse the code from the link for you. auth.signInWithEmailLink(email, emailLink) .addOnCompleteListener { task -> if (task.isSuccessful) { Log.d(TAG, "Successfully signed in with email link!") val result = task.result // You can access the new user via result.getUser() // Additional user info profile *not* available via: // result.getAdditionalUserInfo().getProfile() == null // You can check if the user is new or existing: // result.getAdditionalUserInfo().isNewUser() } else { Log.e(TAG, "Error signing in with email link", task.exception) } } }
Java
FirebaseAuth auth = FirebaseAuth.getInstance(); Intent intent = getIntent(); String emailLink = intent.getData().toString(); // Confirm the link is a sign-in with email link. if (auth.isSignInWithEmailLink(emailLink)) { // Retrieve this from wherever you stored it String email = "someemail@domain.com"; // The client SDK will parse the code from the link for you. auth.signInWithEmailLink(email, emailLink) .addOnCompleteListener(new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { if (task.isSuccessful()) { Log.d(TAG, "Successfully signed in with email link!"); AuthResult result = task.getResult(); // You can access the new user via result.getUser() // Additional user info profile *not* available via: // result.getAdditionalUserInfo().getProfile() == null // You can check if the user is new or existing: // result.getAdditionalUserInfo().isNewUser() } else { Log.e(TAG, "Error signing in with email link", task.getException()); } } }); }
如要進一步瞭解如何在 Apple 應用程式中處理透過電子郵件連結登入帳戶的程序,請參閱 Apple 平台指南。
如要瞭解如何在網頁應用程式中處理透過電子郵件連結登入的程序,請參閱網頁指南。
透過電子郵件連結連結/重新驗證
您也可以將這種驗證方法連結至現有使用者。舉例來說,使用者先前透過其他供應商 (例如電話號碼) 進行驗證,現在可以將這種登入方式新增至現有帳戶。
兩者的差異在於作業的後半部分:
Kotlin
// Construct the email link credential from the current URL. val credential = EmailAuthProvider.getCredentialWithLink(email, emailLink) // Link the credential to the current user. Firebase.auth.currentUser!!.linkWithCredential(credential) .addOnCompleteListener { task -> if (task.isSuccessful) { Log.d(TAG, "Successfully linked emailLink credential!") val result = task.result // You can access the new user via result.getUser() // Additional user info profile *not* available via: // result.getAdditionalUserInfo().getProfile() == null // You can check if the user is new or existing: // result.getAdditionalUserInfo().isNewUser() } else { Log.e(TAG, "Error linking emailLink credential", task.exception) } }
Java
// Construct the email link credential from the current URL. AuthCredential credential = EmailAuthProvider.getCredentialWithLink(email, emailLink); // Link the credential to the current user. auth.getCurrentUser().linkWithCredential(credential) .addOnCompleteListener(new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { if (task.isSuccessful()) { Log.d(TAG, "Successfully linked emailLink credential!"); AuthResult result = task.getResult(); // You can access the new user via result.getUser() // Additional user info profile *not* available via: // result.getAdditionalUserInfo().getProfile() == null // You can check if the user is new or existing: // result.getAdditionalUserInfo().isNewUser() } else { Log.e(TAG, "Error linking emailLink credential", task.getException()); } } });
您也可以使用這項功能,在執行敏感作業前,重新驗證電子郵件連結使用者。
Kotlin
// Construct the email link credential from the current URL. val credential = EmailAuthProvider.getCredentialWithLink(email, emailLink) // Re-authenticate the user with this credential. Firebase.auth.currentUser!!.reauthenticateAndRetrieveData(credential) .addOnCompleteListener { task -> if (task.isSuccessful) { // User is now successfully reauthenticated } else { Log.e(TAG, "Error reauthenticating", task.exception) } }
Java
// Construct the email link credential from the current URL. AuthCredential credential = EmailAuthProvider.getCredentialWithLink(email, emailLink); // Re-authenticate the user with this credential. auth.getCurrentUser().reauthenticateAndRetrieveData(credential) .addOnCompleteListener(new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { if (task.isSuccessful()) { // User is now successfully reauthenticated } else { Log.e(TAG, "Error reauthenticating", task.getException()); } } });
不過,由於流程可能會在原始使用者未登入的其他裝置上結束,因此這項流程可能無法完成。在這種情況下,系統可能會向使用者顯示錯誤訊息,強制他們在同一部裝置上開啟連結。您可以在連結中傳遞某些狀態,提供作業類型和使用者 UID 的相關資訊。
已淘汰:以 Firebase Dynamic Links 為準的驗證
電子郵件連結驗證先前是依賴 Firebase Dynamic Links,但這項服務將於 2025 年 8 月 25 日關閉。
我們已在 Firebase Authentication Android SDK v23.2.0 以上版本和 Firebase BoM v33.9.0 以上版本中,發布替代解決方案。
如果應用程式使用舊版樣式的連結,請將應用程式遷移至新的 Firebase Hosting 系統。
已淘汰:區分電子郵件/密碼和電子郵件連結
如果您是在 2023 年 9 月 15 日當天或之後建立專案,系統預設會啟用電子郵件列舉防護功能。這項功能可提升專案使用者帳戶的安全性,但會停用 fetchSignInMethodsForEmail()
方法,我們先前建議您實作以 ID 為優先的流程。
雖然您可以為專案停用電子郵件列舉防護功能,但我們不建議這麼做。
詳情請參閱電子郵件列舉防護功能的說明文件。
後續步驟
使用者首次登入後,系統會建立新的使用者帳戶,並連結至使用者登入時使用的憑證 (即使用者名稱和密碼、電話號碼或驗證供應商資訊)。這個新帳戶會儲存在 Firebase 專案中,可用於識別專案中每個應用程式的使用者,無論使用者登入方式為何。
-
在應用程式中,您可以從
FirebaseUser
物件取得使用者的基本個人資料資訊。請參閱「 管理使用者」。 在 Firebase Realtime Database 和 Cloud Storage 安全規則中,您可以從
auth
變數取得已登入使用者的專屬使用者 ID, 並使用該 ID 控制使用者可存取的資料。
您可以將驗證供應商憑證連結至現有使用者帳戶,允許使用者透過多個驗證供應商登入應用程式。
如要登出使用者,請呼叫
signOut
:
Kotlin
Firebase.auth.signOut()
Java
FirebaseAuth.getInstance().signOut();