如果您已升級至使用 Identity Platform 的 Firebase 驗證,則可在應用程式中新增動態密碼 (TOTP) 多因素驗證 (MFA)。
透過 Identity Platform 進行 Firebase 驗證,您可以使用 TOTP 做為 MFA 的額外因素。啟用這項功能後,嘗試登入應用程式時的使用者會看到 TOTP 要求。如要產生驗證碼,應用程式必須使用能夠產生有效 TOTP 驗證碼的驗證器應用程式,例如 Google Authenticator。
事前準備
請至少啟用一個支援 MFA 的提供者。請注意,除了下列支援 MFA 的所有供應商中,所有提供者均適用:
- 電話驗證
- 匿名驗證
- 自訂驗證權杖
- Apple 遊戲中心
確認您的應用程式會驗證使用者電子郵件地址。MFA 需要電子郵件驗證。這樣可以防止惡意人士使用非他們擁有的電子郵件地址註冊服務,然後再新增第二個因素,鎖定電子郵件地址的實際擁有者。
如果您尚未安裝 Firebase Android SDK,請先安裝。
TOTP MFA 僅適用於 Android SDK v22.1.0 以上版本。
啟用 TOTP MFA
如要啟用 TOTP 做為第二因素,請使用 Admin SDK 或呼叫專案設定 REST 端點。
如要使用 Admin SDK,請按照下列步驟操作:
如果您尚未安裝 Firebase Admin Node.js SDK,請先完成安裝。
TOTP MFA 僅適用於 Firebase Admin Node.js SDK 11.6.0 以上版本。
執行以下指令:
import { getAuth } from 'firebase-admin/auth'; getAuth().projectConfigManager().updateProjectConfig( { multiFactorConfig: { providerConfigs: [{ state: "ENABLED", totpProviderConfig: { adjacentIntervals: { NUM_ADJ_INTERVALS }, } }] } })
更改下列內容:
NUM_ADJ_INTERVALS
:可接收 TOTP 的相鄰時間範圍間隔數量 (從 0 到 10)。預設值為五。TOTP 的運作原理是確保當兩方 (驗證者和驗證工具) 於相同時間範圍內 (通常為 30 秒) 產生動態密碼時,即可產生相同的密碼。不過,為了因應各方與人為回應時間的時鐘偏移,您可以將 TOTP 服務設定為也接受相鄰視窗的 TOTP。
如要使用 REST API 啟用 TOTP MFA,請執行下列指令:
curl -X PATCH "https://identitytoolkit.googleapis.com/admin/v2/projects/PROJECT_ID/config?updateMask=mfa" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
-H "X-Goog-User-Project: PROJECT_ID" \
-d \
'{
"mfa": {
"providerConfigs": [{
"state": "ENABLED",
"totpProviderConfig": {
"adjacentIntervals": "NUM_ADJ_INTERVALS"
}
}]
}
}'
更改下列內容:
PROJECT_ID
:專案 ID。NUM_ADJ_INTERVALS
:時間範圍間隔 (從 0 到 10)。預設值為 5。TOTP 的運作原理是確保當兩方 (驗證者和驗證工具) 於相同時間範圍內 (通常為 30 秒) 產生動態密碼時,即可產生相同的密碼。不過,為了因應各方與人為回應時間的時鐘偏移,您可以將 TOTP 服務設定為也接受相鄰視窗的 TOTP。
選擇註冊模式
您可以選擇應用程式是否需要多重驗證,以及註冊使用者的方式和時機。常見的模式如下:
在註冊過程中註冊使用者的第二重驗證步驟。如果您的應用程式需要所有使用者的多重驗證,請使用此方法。
在註冊過程中提供可略過選項,以註冊雙重驗證。如果您要在應用程式中鼓勵 (但不要求多重驗證),可以使用此方法。
讓使用者能在帳戶或設定檔管理頁面 (而非註冊畫面) 新增雙重驗證。這樣就能盡量減少註冊過程中的阻礙,同時仍為注重安全性的使用者提供多重驗證功能。
如果使用者要存取強化安全性需求的功能時,必須逐步新增第二重驗證條件。
為使用者註冊 TOTP MFA
啟用 TOTP MFA 做為應用程式的第二因素後,請實作用戶端邏輯,以將使用者註冊至 TOTP MFA:
重新驗證使用者。
為已驗證的使用者產生 TOTP 密鑰:
// Generate a TOTP secret. Firebase.auth.currentUser.multiFactor.session .addOnSuccessListener { multiFactorSession -> TotpMultiFactorGenerator.generateSecret(multiFactorSession) .addOnSuccessListener { totpSecret -> // Display the secret to the user and prompt them to // enter it into their authenticator app. (See the next // step.) } }
向使用者顯示密鑰,並提示他們在驗證器應用程式中輸入密鑰:
// Display this key: val secret = totpSecret.sharedSecretKey
除了顯示密鑰之外,您也可以嘗試自動將金鑰新增至裝置的預設驗證器應用程式。如要這麼做,請產生 Google Authenticator 相容的金鑰 URI,並將其傳送至
openInOtpApp()
:val qrCodeUri = totpSecret.generateQrCodeUrl( currentUser.email ?: "default account", "Your App Name") totpSecret.openInOtpApp(qrCodeUri)
使用者將密鑰新增至驗證器應用程式後,就會開始產生 TOTP。
提示使用者輸入驗證器應用程式顯示的 TOTP,並使用該工具完成 MFA 註冊:
// Ask the user for a verification code from the authenticator app. val verificationCode = // Code from user input. // Finalize the enrollment. val multiFactorAssertion = TotpMultiFactorGenerator .getAssertionForEnrollment(totpSecret, verificationCode) Firebase.auth.currentUser.multiFactor.enroll(multiFactorAssertion, "TOTP") .addOnSuccessListener { // Enrollment complete. }
透過第二重驗證方式登入使用者
如要透過 TOTP MFA 讓使用者登入,請使用以下代碼:
按照未使用 MFA 的方式呼叫其中一個
signInWith
方法。(例如signInWithEmailAndPassword()
)。如果方法擲回FirebaseAuthMultiFactorException
,請啟動應用程式的 MFA 流程。Firebase.auth.signInWithEmailAndPassword(email, password) .addOnSuccessListener { result -> // If the user is not enrolled with a second factor and provided valid // credentials, sign-in succeeds. // (If your app requires MFA, this could be considered an error // condition, which you would resolve by forcing the user to enroll a // second factor.) // ... } .addOnFailureListener { exception -> when (exception) { is FirebaseAuthMultiFactorException -> { // Initiate your second factor sign-in flow. (See next step.) // ... } } }
應用程式的 MFA 流程應先提示使用者選擇要使用的第二個因素。如要取得支援的第二個因素清單,請查看
MultiFactorResolver
執行個體的hints
屬性:val enrolledFactors = exception.resolver.hints.map { it.displayName }
如果使用者選擇使用 TOTP,請提示他們輸入驗證器應用程式上顯示的 TOTP,並使用它登入:
when (exception.resolver.hints[selectedIndex].factorId) { TotpMultiFactorGenerator.FACTOR_ID -> { val otpFromAuthenticator = // OTP typed by the user. val assertion = TotpMultiFactorGenerator.getAssertionForSignIn( exception.resolver.hints[selectedIndex].uid, otpFromAuthenticator ) exception.resolver.resolveSignIn(assertion) .addOnSuccessListener { result -> // Successfully signed in! } .addOnFailureListener { resolveError -> // Invalid or expired OTP. } } PhoneMultiFactorGenerator.FACTOR_ID -> { // Handle SMS second factor. } }
取消註冊 TOTP MFA
本節說明如何處理使用者取消註冊 TOTP MFA 的行為。
如果使用者已註冊多個 MFA 選項,且取消註冊最近啟用的選項,則使用者會收到 auth/user-token-expired
並登出。使用者必須重新登入並驗證現有的憑證,例如電子郵件地址和密碼。
如要為使用者取消註冊、處理錯誤並觸發重新驗證,請使用下列程式碼:
Firebase.auth.currentUser.multiFactor.unenroll(mfaEnrollmentId)
.addOnSuccessListener {
// Second factor unenrolled.
}
.addOnFailureListener { exception ->
when (exception) {
is FirebaseAuthInvalidUserException -> {
// Second factor unenrolled. If the user was signed out, re-authenticate
// them.
// For example, if they signed in with a password, prompt them to
// provide it again, then call `reauthenticateWithCredential()` as shown
// below.
val credential = EmailAuthProvider.getCredential(email, password)
currentUser.reauthenticate(credential)
.addOnSuccessListener {
// Success!
}
.addOnFailureListener {
// Bad email address and password combination.
}
}
}
}
後續步驟
- 透過 Admin SDK,以程式輔助的方式管理多重使用者。