如果已升級至 Firebase Authentication with Identity Platform,您可以在應用程式中新增限時動態密碼 (TOTP) 多重驗證 (MFA)。
Firebase Authentication with Identity Platform 可讓您使用 TOTP 做為 MFA 的額外因素。啟用這項功能後,嘗試登入應用程式的使用者會看到 TOTP 要求。如要產生驗證碼,使用者必須使用可產生有效 TOTP 驗證碼的驗證器應用程式,例如 Google Authenticator。
事前準備
啟用至少一個支援 MFA 的供應商。請注意,下列供應商除外,所有供應商都支援多重驗證:
- 電話驗證
- 匿名驗證
- 自訂驗證權杖
- Apple Game Center
確保應用程式會驗證使用者電子郵件地址。多重驗證需要電子郵件驗證。這麼做可防止惡意人士使用不屬於自己的電子郵件地址註冊服務,然後新增第二個驗證因素,將電子郵件地址的實際擁有者鎖在門外。
如果尚未安裝,請安裝 Firebase JavaScript SDK。
TOTP MFA 僅支援模組化 Web SDK,版本為 v9.19.1 以上。
啟用 TOTP 多重驗證
如要啟用 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 的相鄰時間視窗間隔數,範圍為零到十。預設值為 5。TOTP 的運作方式是確保兩方 (驗證者和驗證器) 在同一時間範圍 (通常為 30 秒) 內產生 OTP 時,會產生相同的密碼。不過,為因應雙方時鐘不同步的情況,以及人類的回應時間,您可以設定 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
:時間範圍間隔數,從零到十。預設值為五。TOTP 的運作方式是確保兩方 (驗證者和驗證器) 在同一時間範圍 (通常為 30 秒) 內產生 OTP 時,會產生相同的密碼。不過,為因應雙方時鐘不同步的情況,以及人類的回應時間,您可以設定 TOTP 服務,讓系統也接受相鄰時間範圍內的 TOTP。
選擇註冊模式
您可以選擇應用程式是否需要多重驗證,以及如何和何時註冊使用者。常見的模式包括:
在註冊程序中,為使用者註冊第二重驗證。如果應用程式要求所有使用者都必須進行多重驗證,請使用這個方法。
在註冊期間提供可略過的選項,讓使用者註冊第二個驗證因素。如果您想鼓勵使用者在應用程式中啟用多重驗證,但並非強制要求,或許可以採用這種做法。
提供從使用者帳戶或個人資料管理頁面新增第二個驗證因素的功能,而非註冊畫面。這樣可盡量減少註冊程序中的阻礙,同時仍為注重安全性的使用者提供多重驗證功能。
當使用者想存取安全性要求較高的功能時,逐步要求新增第二個驗證因素。
為使用者啟用 TOTP 多重驗證
為應用程式啟用 TOTP MFA 做為第二重驗證後,請實作用戶端邏輯,讓使用者註冊 TOTP MFA:
匯入必要的 MFA 類別和函式:
import { multiFactor, TotpMultiFactorGenerator, TotpSecret, getAuth, } from "firebase/auth";
重新驗證使用者。
為通過驗證的使用者產生 TOTP 密鑰:
// Generate a TOTP secret. const multiFactorSession = await multiFactor(currentUser).getSession(); const totpSecret = await TotpMultiFactorGenerator.generateSecret( multiFactorSession );
向使用者顯示密碼,並提示他們在驗證器應用程式中輸入密碼。
許多驗證器應用程式都提供 QR code 掃描功能,使用者只要掃描代表 Google Authenticator 相容金鑰 URI 的 QR code,即可快速新增 TOTP 密碼。如要產生這類 QR code,請使用
generateQrCodeUrl()
產生 URI,然後使用您選擇的 QR code 程式庫進行編碼。例如:const totpUri = totpSecret.generateQrCodeUrl( currentUser.email, "Your App's Name" ); await QRExampleLib.toCanvas(totpUri, qrElement);
無論是否顯示 QR code,請一律顯示私密金鑰,以支援無法讀取 QR code 的驗證器應用程式:
// Also display this key: const secret = totpSecret.secretKey;
使用者將密碼新增至驗證器應用程式後,應用程式就會開始產生 TOTP。
提示使用者輸入驗證器應用程式顯示的 TOTP,並使用該 TOTP 完成多重驗證註冊:
// Ask the user for a verification code from the authenticator app. const verificationCode = // Code from user input. // Finalize the enrollment. const multiFactorAssertion = TotpMultiFactorGenerator.assertionForEnrollment( totpSecret, verificationCode ); await multiFactor(currentUser).enroll(multiFactorAssertion, mfaDisplayName);
透過第二個驗證因素登入使用者
如要使用 TOTP 多重驗證登入使用者,請使用下列程式碼:
匯入必要的 MFA 類別和函式:
import { getAuth, getMultiFactorResolver, TotpMultiFactorGenerator, } from "firebase/auth";
呼叫其中一個
signInWith
方法,就像您未使用 MFA 時一樣。 (例如signInWithEmailAndPassword()
)。如果方法擲回auth/multi-factor-auth-required
錯誤,請啟動應用程式的 MFA 流程。try { const userCredential = await signInWithEmailAndPassword( getAuth(), email, password ); // 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.) // ... } catch (error) { switch (error.code) { case "auth/multi-factor-auth-required": // Initiate your second factor sign-in flow. (See next step.) // ... break; case ...: // Handle other errors, such as wrong passwords. break; } }
應用程式的 MFA 流程應先提示使用者選擇要使用的第二個驗證因素。您可以檢查
MultiFactorResolver
執行個體的hints
屬性,取得支援的第二個驗證因素清單:const mfaResolver = getMultiFactorResolver(getAuth(), error); const enrolledFactors = mfaResolver.hints.map(info => info.displayName);
如果使用者選擇使用 TOTP,請提示他們輸入驗證器應用程式顯示的 TOTP,並用來登入:
switch (mfaResolver.hints[selectedIndex].factorId) { case TotpMultiFactorGenerator.FACTOR_ID: const otpFromAuthenticator = // OTP typed by the user. const multiFactorAssertion = TotpMultiFactorGenerator.assertionForSignIn( mfaResolver.hints[selectedIndex].uid, otpFromAuthenticator ); try { const userCredential = await mfaResolver.resolveSignIn( multiFactorAssertion ); // Successfully signed in! } catch (error) { // Invalid or expired OTP. } break; case PhoneMultiFactorGenerator.FACTOR_ID: // Handle SMS second factor. break; default: // Unsupported second factor? break; }
取消註冊 TOTP 多重驗證
本節說明如何處理使用者取消註冊 TOTP MFA。
如果使用者註冊了多個多重驗證選項,且取消註冊最近啟用的選項,系統會顯示 auth/user-token-expired
並將使用者登出。使用者必須重新登入並驗證現有憑證,例如電子郵件地址和密碼。
如要取消註冊使用者、處理錯誤及觸發重新驗證,請使用下列程式碼:
import {
EmailAuthProvider,
TotpMultiFactorGenerator,
getAuth,
multiFactor,
reauthenticateWithCredential,
} from "firebase/auth";
try {
// Unenroll from TOTP MFA.
await multiFactor(currentUser).unenroll(mfaEnrollmentId);
} catch (error) {
if (error.code === 'auth/user-token-expired') {
// 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.
const credential = EmailAuthProvider.credential(email, password);
await reauthenticateWithCredential(
currentUser,
credential
);
}
}
後續步驟
- 使用 Admin SDK,以程式輔助的方式管理多重驗證使用者。