如果您已升級至 Firebase Authentication with Identity Platform,即可新增簡訊多重驗證 您的 iOS 應用程式。
多重驗證可提高應用程式安全性。雖然攻擊者 經常會竊取密碼和社群媒體帳戶、攔截簡訊, 變得更困難
事前準備
請至少啟用一個支援多重驗證的供應商。 每個供應商都支援多重驗證,但電話驗證、匿名驗證和 Apple Game Center。
確認應用程式正在驗證使用者的電子郵件地址。MFA 需要電子郵件驗證。 這可防止惡意人士利用電子郵件註冊服務 成為非擁有人,進而鎖定真正的擁有者 。
啟用多重驗證
開啟「驗證 >登入方式 Firebase控制台中的頁面。
在「進階」部分中,啟用「簡訊多重驗證」。
請一併輸入要測試應用程式的電話號碼。 雖然非必要,但我們強烈建議您註冊測試電話號碼 避免開發過程中發生節流現象
如果您尚未授權應用程式的網域,請將網域新增至允許清單 [驗證] > 中的清單設定 Firebase控制台中的頁面。
驗證應用程式
「Firebase」需要驗證簡訊要求是否確實來自您的 應用程式。操作方式有以下兩種:
靜音 APN 通知:使用者首次登入時, Firebase 可以將無訊息的推播通知傳送到使用者的 裝置。如果應用程式收到通知,驗證作業就會繼續。 請注意,從 iOS 8.0 開始,您不需要要求使用者允許推送 通知使用這個方法
reCAPTCHA 驗證:如果您無法傳送無聲通知 (例如: 例如,使用者已停用背景重新整理,或者您正在測試 匯入應用程式),您可以使用 reCAPTCHA。在許多情況下 reCAPTCHA 會自動解決,使用者完全不需要進行互動。
使用靜音通知
如何啟用 APN 通知以便與 Firebase 搭配使用:
在 Xcode 中啟用推播通知 。
透過 Firebase 控制台上傳 APN 驗證金鑰 (變更的內容) 會自動移轉至 Google Cloud Firebase)。 如果您沒有 APN 驗證金鑰,請參閱 使用 FCM 設定 APN 以便瞭解如何取得
開啟 Firebase 控制台。
前往「專案設定」。
選取「雲端通訊」分頁標籤。
在「APNs 驗證金鑰」下方的「iOS 應用程式設定」下方 部分中,按一下「上傳」。
選取金鑰。
新增該金鑰的金鑰 ID。金鑰 ID 位於 憑證、ID 與設定檔 Apple Developer Member Center。
按一下 [上傳]。
如果您已有 APN 憑證,可改為上傳憑證。
使用 reCAPTCHA 驗證
如何為用戶端 SDK 啟用 reCAPTCHA:
在 Xcode 中開啟專案設定。
按一下左側樹狀檢視中的專案名稱。
從「Targets」(目標) 部分選取您的應用程式。
選取「資訊」分頁標籤。
展開「網址類型」部分。
按一下「+」按鈕。
在「網址配置」欄位中輸入撤銷的用戶端 ID。您可以 這個值列在
GoogleService-Info.plist
設定檔中REVERSED_CLIENT_ID
。
完成後,設定應如下所示:
您可以視需求自訂應用程式呈現
SFSafariViewController
或 UIWebView
。待辦
建立符合 FIRAuthUIDelegate
通訊協定的自訂類別。
並傳遞至 verifyPhoneNumber:UIDelegate:completion:
選擇註冊模式
您可以選擇是否要讓應用程式需要多因素驗證,以及如何 以及註冊使用者的時間常見的模式包括:
註冊使用者的第二重驗證在註冊過程中。使用這份草稿 方法。 請注意,帳戶必須擁有經過驗證的電子郵件地址才能註冊第二個帳戶 以確保註冊流程必須滿足上述需求。
提供可略過的選項,讓使用者在註冊期間註冊第二個步驟。應用程式 想鼓勵但不要求進行多因素驗證時 他們偏好使用這個方法。
讓使用者能夠在帳戶或設定檔中新增次要驗證條件 而非註冊畫面這可以大幅減少 同時在進行多因素驗證時 。
使用者要存取應用程式時,需要逐步新增第二個驗證步驟 強化安全性要求的功能
註冊次要驗證方式
如何為使用者註冊新的次要驗證條件:
重新驗證使用者。
請使用者輸入電話號碼。
為使用者取得多重要素工作階段:
Swift
authResult.user.multiFactor.getSessionWithCompletion() { (session, error) in // ... }
目標-C
[authResult.user.multiFactor getSessionWithCompletion:^(FIRMultiFactorSession * _Nullable session, NSError * _Nullable error) { // ... }];
傳送驗證訊息至使用者的手機。確認電話號碼為 格式為
+
,而且沒有其他標點符號或空白字元 (適用於 例如:+15105551234
)Swift
// Send SMS verification code. PhoneAuthProvider.provider().verifyPhoneNumber( phoneNumber, uiDelegate: nil, multiFactorSession: session) { (verificationId, error) in // verificationId will be needed for enrollment completion. }
目標-C
// Send SMS verification code. [FIRPhoneAuthProvider.provider verifyPhoneNumber:phoneNumber UIDelegate:nil multiFactorSession:session completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) { // verificationId will be needed for enrollment completion. }];
雖然並非必要,但最佳做法是事先告知使用者 會收到簡訊,支付一般簡訊費用
verifyPhoneNumber()
方法會從以下位置啟動應用程式驗證程序: 背景發出推播通知如果靜音推播通知處於 無法使用,則會收到 reCAPTCHA 驗證訊息。讓系統傳送簡訊驗證碼後,要求使用者驗證驗證碼。接著,使用 回應來建立
PhoneAuthCredential
:Swift
// Ask user for the verification code. Then: let credential = PhoneAuthProvider.provider().credential( withVerificationID: verificationId, verificationCode: verificationCode)
目標-C
// Ask user for the SMS verification code. Then: FIRPhoneAuthCredential *credential = [FIRPhoneAuthProvider.provider credentialWithVerificationID:verificationID verificationCode:kPhoneSecondFactorVerificationCode];
初始化斷言物件:
Swift
let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
目標-C
FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
完成註冊程序。您也可以選擇為 第二個步驟這項功能適用於具有多項第二項因素的使用者 系統會在驗證流程中遮蓋電話號碼 (例如, 例如 +1******1234)。
Swift
// Complete enrollment. This will update the underlying tokens // and trigger ID token change listener. user.multiFactor.enroll(with: assertion, displayName: displayName) { (error) in // ... }
目標-C
// Complete enrollment. This will update the underlying tokens // and trigger ID token change listener. [authResult.user.multiFactor enrollWithAssertion:assertion displayName:nil completion:^(NSError * _Nullable error) { // ... }];
以下程式碼顯示第二重驗證註冊的完整範例:
Swift
let user = Auth.auth().currentUser
user?.multiFactor.getSessionWithCompletion({ (session, error) in
// Send SMS verification code.
PhoneAuthProvider.provider().verifyPhoneNumber(
phoneNumber,
uiDelegate: nil,
multiFactorSession: session
) { (verificationId, error) in
// verificationId will be needed for enrollment completion.
// Ask user for the verification code.
let credential = PhoneAuthProvider.provider().credential(
withVerificationID: verificationId!,
verificationCode: phoneSecondFactorVerificationCode)
let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
// Complete enrollment. This will update the underlying tokens
// and trigger ID token change listener.
user?.multiFactor.enroll(with: assertion, displayName: displayName) { (error) in
// ...
}
}
})
目標-C
FIRUser *user = FIRAuth.auth.currentUser;
[user.multiFactor getSessionWithCompletion:^(FIRMultiFactorSession * _Nullable session,
NSError * _Nullable error) {
// Send SMS verification code.
[FIRPhoneAuthProvider.provider
verifyPhoneNumber:phoneNumber
UIDelegate:nil
multiFactorSession:session
completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) {
// verificationId will be needed for enrollment completion.
// Ask user for the verification code.
// ...
// Then:
FIRPhoneAuthCredential *credential =
[FIRPhoneAuthProvider.provider credentialWithVerificationID:verificationID
verificationCode:kPhoneSecondFactorVerificationCode];
FIRMultiFactorAssertion *assertion =
[FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
// Complete enrollment. This will update the underlying tokens
// and trigger ID token change listener.
[user.multiFactor enrollWithAssertion:assertion
displayName:displayName
completion:^(NSError * _Nullable error) {
// ...
}];
}];
}];
恭喜!您已成功註冊以下項目的第二個驗證方式: 而非個別使用者的帳戶
透過次要驗證方式登入使用者
如何透過雙重簡訊驗證功能登入使用者帳戶:
透過第一個驗證方式登入使用者,然後擷取指出錯誤訊息 需要多重驗證。這項錯誤包含解析器 關於已註冊雙重驗證和基礎工作階段的提示 證明使用者已透過第一個因素成功通過驗證。
舉例來說,如果使用者的第一個驗證方法是電子郵件地址和密碼:
Swift
Auth.auth().signIn( withEmail: email, password: password ) { (result, error) in let authError = error as NSError if authError?.code == AuthErrorCode.secondFactorRequired.rawValue { // The user is a multi-factor user. Second factor challenge is required. let resolver = authError!.userInfo[AuthErrorUserInfoMultiFactorResolverKey] as! MultiFactorResolver // ... } else { // Handle other errors such as wrong password. } }
目標-C
[FIRAuth.auth signInWithEmail:email password:password completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) { if (error == nil || error.code != FIRAuthErrorCodeSecondFactorRequired) { // User is not enrolled with a second factor and is successfully signed in. // ... } else { // The user is a multi-factor user. Second factor challenge is required. } }];
如果使用者的第一個因素是聯合提供者 (例如 OAuth),請擷取 呼叫
getCredentialWith()
後發生錯誤。如果使用者已註冊多項次要驗證因素,請詢問他們哪個 。您可以透過
resolver.hints[selectedIndex].phoneNumber
,以及含有resolver.hints[selectedIndex].displayName
。Swift
// Ask user which second factor to use. Then: if resolver.hints[selectedIndex].factorID == PhoneMultiFactorID { // User selected a phone second factor. // ... } else if resolver.hints[selectedIndex].factorID == TotpMultiFactorID { // User selected a TOTP second factor. // ... } else { // Unsupported second factor. }
目標-C
FIRMultiFactorResolver *resolver = (FIRMultiFactorResolver *) error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey]; // Ask user which second factor to use. Then: FIRPhoneMultiFactorInfo *hint = (FIRPhoneMultiFactorInfo *) resolver.hints[selectedIndex]; if (hint.factorID == FIRPhoneMultiFactorID) { // User selected a phone second factor. // ... } else if (hint.factorID == FIRTOTPMultiFactorID) { // User selected a TOTP second factor. // ... } else { // Unsupported second factor. }
傳送驗證訊息到使用者的手機:
Swift
// Send SMS verification code. let hint = resolver.hints[selectedIndex] as! PhoneMultiFactorInfo PhoneAuthProvider.provider().verifyPhoneNumber( with: hint, uiDelegate: nil, multiFactorSession: resolver.session ) { (verificationId, error) in // verificationId will be needed for sign-in completion. }
目標-C
// Send SMS verification code [FIRPhoneAuthProvider.provider verifyPhoneNumberWithMultiFactorInfo:hint UIDelegate:nil multiFactorSession:resolver.session completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) { if (error != nil) { // Failed to verify phone number. } }];
傳送簡訊後,請要求使用者驗證驗證碼,並使用該驗證碼 建構
PhoneAuthCredential
:Swift
// Ask user for the verification code. Then: let credential = PhoneAuthProvider.provider().credential( withVerificationID: verificationId!, verificationCode: verificationCodeFromUser)
目標-C
// Ask user for the SMS verification code. Then: FIRPhoneAuthCredential *credential = [FIRPhoneAuthProvider.provider credentialWithVerificationID:verificationID verificationCode:verificationCodeFromUser];
使用憑證初始化斷言物件:
Swift
let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
目標-C
FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
解決登入問題。接下來,您可以存取原始的登入結果 包含標準供應商專屬資料和驗證憑證:
Swift
// Complete sign-in. This will also trigger the Auth state listeners. resolver.resolveSignIn(with: assertion) { (authResult, error) in // authResult will also contain the user, additionalUserInfo, optional // credential (null for email/password) associated with the first factor sign-in. // For example, if the user signed in with Google as a first factor, // authResult.additionalUserInfo will contain data related to Google provider that // the user signed in with. // user.credential contains the Google OAuth credential. // user.credential.accessToken contains the Google OAuth access token. // user.credential.idToken contains the Google OAuth ID token. }
目標-C
// Complete sign-in. [resolver resolveSignInWithAssertion:assertion completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) { if (error != nil) { // User successfully signed in with the second factor phone number. } }];
以下程式碼是多因素使用者登入的完整範例:
Swift
Auth.auth().signIn(
withEmail: email,
password: password
) { (result, error) in
let authError = error as NSError?
if authError?.code == AuthErrorCode.secondFactorRequired.rawValue {
let resolver =
authError!.userInfo[AuthErrorUserInfoMultiFactorResolverKey] as! MultiFactorResolver
// Ask user which second factor to use.
// ...
// Then:
let hint = resolver.hints[selectedIndex] as! PhoneMultiFactorInfo
// Send SMS verification code
PhoneAuthProvider.provider().verifyPhoneNumber(
with: hint,
uiDelegate: nil,
multiFactorSession: resolver.session
) { (verificationId, error) in
if error != nil {
// Failed to verify phone number.
}
// Ask user for the SMS verification code.
// ...
// Then:
let credential = PhoneAuthProvider.provider().credential(
withVerificationID: verificationId!,
verificationCode: verificationCodeFromUser)
let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
// Complete sign-in.
resolver.resolveSignIn(with: assertion) { (authResult, error) in
if error != nil {
// User successfully signed in with the second factor phone number.
}
}
}
}
}
目標-C
[FIRAuth.auth signInWithEmail:email
password:password
completion:^(FIRAuthDataResult * _Nullable authResult,
NSError * _Nullable error) {
if (error == nil || error.code != FIRAuthErrorCodeSecondFactorRequired) {
// User is not enrolled with a second factor and is successfully signed in.
// ...
} else {
FIRMultiFactorResolver *resolver =
(FIRMultiFactorResolver *) error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey];
// Ask user which second factor to use.
// ...
// Then:
FIRPhoneMultiFactorInfo *hint = (FIRPhoneMultiFactorInfo *) resolver.hints[selectedIndex];
// Send SMS verification code
[FIRPhoneAuthProvider.provider
verifyPhoneNumberWithMultiFactorInfo:hint
UIDelegate:nil
multiFactorSession:resolver.session
completion:^(NSString * _Nullable verificationID,
NSError * _Nullable error) {
if (error != nil) {
// Failed to verify phone number.
}
// Ask user for the SMS verification code.
// ...
// Then:
FIRPhoneAuthCredential *credential =
[FIRPhoneAuthProvider.provider
credentialWithVerificationID:verificationID
verificationCode:kPhoneSecondFactorVerificationCode];
FIRMultiFactorAssertion *assertion =
[FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
// Complete sign-in.
[resolver resolveSignInWithAssertion:assertion
completion:^(FIRAuthDataResult * _Nullable authResult,
NSError * _Nullable error) {
if (error != nil) {
// User successfully signed in with the second factor phone number.
}
}];
}];
}
}];
恭喜!您已成功透過多重要素登入使用者 驗證。
後續步驟
- 管理多重驗證使用者 透過程式利用 Admin SDK。