如果您已升級至 Firebase Authentication with Identity Platform,可以為應用程式新增限時動態密碼 (TOTP) 多重驗證 (MFA)。
Firebase Authentication with Identity Platform 可讓您使用 TOTP 做為 MFA 的額外因素。啟用這項功能後,使用者嘗試登入應用程式時,就會看到 TOTP 的要求。如要產生此類驗證碼,使用者必須使用可產生有效 TOTP 驗證碼的驗證程式應用程式,例如 Google Authenticator。
事前準備
請啟用至少一個支援 MFA 的供應商。請注意,除了以下供應商以外,所有供應商都支援多重認證:
- 電話驗證
- 匿名驗證
- 自訂驗證權杖
- Apple Game Center
請確認您的應用程式會驗證使用者的電子郵件地址。多重驗證功能需要通過電子郵件驗證。這麼做可防止惡意人士使用不屬於自己的電子郵件地址註冊服務,然後透過新增第二個因素,將電子郵件地址的實際擁有者鎖在門外。
如果您尚未安裝 Firebase Apple SDK,請先安裝。
二階段驗證碼 MFA 僅支援 Apple SDK 10.12.0 以上版本,且僅適用於 iOS。
啟用 TOTP MFA
如要啟用 TOTP 做為次要驗證方法,請使用 Admin SDK 或呼叫專案設定 REST 端點。
如要使用 Admin SDK,請執行下列操作:
如果您尚未安裝 Firebase Admin Node.js SDK,請先安裝。
Firebase Admin Node.js SDK 11.6.0 以上版本僅支援 TOTP MFA。
執行以下指令:
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
:時間區間間隔數量,從零到十。預設值為 5。TOTP 的運作方式是確保雙方 (驗證者和驗證者) 在相同的時間範圍內 (通常為 30 秒) 產生 OTP,產生的密碼都相同。不過,為了配合各方與人為回應時間之間的時鐘偏差,您可以將 TOTP 服務設定為也接受相鄰視窗的 TOTP。
選擇註冊模式
您可以選擇應用程式是否需要多重驗證,以及註冊使用者的方式和時間。以下列舉幾個常見的模式:
在註冊過程中註冊使用者的第二重驗證。如果應用程式需要所有使用者的多重驗證,請使用這個方法。
提供可略過的選項,讓使用者在註冊時註冊第二重驗證。如果您想在應用程式中鼓勵使用多重驗證,但不強制要求使用,可以採用這種做法。
能夠從使用者帳戶或設定檔管理頁面 (而非註冊畫面) 新增第二重驗證方式。這樣可盡量減少註冊過程中的阻礙,同時讓有安全性考量的使用者可以使用多重要素驗證功能。
當使用者想要存取需要更高安全性要求的功能時,要求逐步新增第二個因素。
讓使用者註冊 TOTP 多重驗證
將 TOTP 多重驗證機制設為應用程式的第二個驗證機制後,請實作用戶端邏輯,讓使用者註冊 TOTP 多重驗證機制:
重新驗證使用者。
為已驗證的使用者產生 TOTP 密鑰:
// Generate a TOTP secret. guard let mfaSession = try? await currentUser.multiFactor.session() else { return } guard let totpSecret = try? await TOTPMultiFactorGenerator.generateSecret(with: mfaSession) else { return } // Display the secret to the user and prompt them to enter it into their // authenticator app. (See the next step.)
向使用者顯示密鑰,並提示他們輸入密鑰至驗證器應用程式:
// Display this key: let secret = totpSecret.sharedSecretKey()
除了顯示密鑰,您也可以嘗試自動將其新增至裝置的預設驗證器應用程式。方法是產生與 Google Authenticator 相容的金鑰 URI,並傳送至
openInOTPApp(withQRCodeURL:)
:let otpAuthUri = totpSecret.generateQRCodeURL( withAccountName: currentUser.email ?? "default account", issuer: "Your App Name") totpSecret.openInOTPApp(withQRCodeURL: otpAuthUri)
使用者將秘密金鑰新增至驗證器應用程式後,系統就會開始產生 TOTP。
提示使用者輸入 Authenticator 應用程式顯示的 TOTP,並使用該值完成多因素驗證註冊程序:
// Ask the user for a verification code from the authenticator app. let verificationCode = // Code from user input. // Finalize the enrollment. let multiFactorAssertion = TOTPMultiFactorGenerator.assertionForEnrollment( with: totpSecret, oneTimePassword: verificationCode) do { try await currentUser.multiFactor.enroll( with: multiFactorAssertion, displayName: "TOTP") } catch { // Wrong or expired OTP. Re-prompt the user. }
透過雙重驗證登入使用者
如要使用 TOTP 多重驗證登入使用者,請使用下列程式碼:
如同未使用 MFA 時一樣,呼叫其中一個
signIn(with...:)
方法 (例如signIn(withEmail:password:)
)。如果方法擲回錯誤代碼secondFactorRequired
,請啟動應用程式的 MFA 流程。do { let authResult = try await Auth.auth().signIn(withEmail: email, password: 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 let error as AuthErrorCode where error.code == .secondFactorRequired { // Initiate your second factor sign-in flow. (See next step.) // ... } catch { // Other auth error. throw error }
應用程式的 MFA 流程應先提示使用者選擇要使用的次要驗證方式。您可以查看
MultiFactorResolver
例項的hints
屬性,取得支援的第二種驗證方式清單:let mfaKey = AuthErrorUserInfoMultiFactorResolverKey guard let resolver = error.userInfo[mfaKey] as? MultiFactorResolver else { return } let enrolledFactors = resolver.hints.map(\.displayName)
如果使用者選擇使用 TOTP,請提示他們輸入 Authenticator 應用程式顯示的 TOTP,並使用該代碼登入:
let multiFactorInfo = resolver.hints[selectedIndex] switch multiFactorInfo.factorID { case TOTPMultiFactorID: let otpFromAuthenticator = // OTP typed by the user. let assertion = TOTPMultiFactorGenerator.assertionForSignIn( withEnrollmentID: multiFactorInfo.uid, oneTimePassword: otpFromAuthenticator) do { let authResult = try await resolver.resolveSignIn(with: assertion) } catch { // Wrong or expired OTP. Re-prompt the user. } default: return }
取消註冊 TOTP 多重驗證
本節說明如何處理使用者取消註冊 TOTP MFA 的情況。
如果使用者已註冊多個多重驗證選項,且從最近啟用的選項取消註冊,系統會傳送 auth/user-token-expired
並登出使用者。使用者必須再次登入並驗證現有憑證,例如電子郵件地址和密碼。
如要取消註冊使用者、處理錯誤,並觸發重新驗證程序,請使用下列程式碼:
guard let currentUser = Auth.auth().currentUser else { return }
// Prompt the user to select a factor to unenroll, from this array:
currentUser.multiFactor.enrolledFactors
// ...
// Unenroll the second factor.
let multiFactorInfo = currentUser.multiFactor.enrolledFactors[selectedIndex]
do {
try await currentUser.multiFactor.unenroll(with: multiFactorInfo)
} catch let error as AuthErrorCode where error.code == .invalidUserToken {
// Second factor unenrolled, but the user was signed out. Re-authenticate
// them.
}
後續步驟
- 使用 Admin SDK 以程式輔助方式管理多重要素使用者。