เพิ่มการตรวจสอบสิทธิ์แบบหลายปัจจัยให้กับแอป iOS ของคุณ

หากคุณอัปเกรดเป็น Firebase Authentication ด้วย Identity Platform แล้ว คุณจะเพิ่มการตรวจสอบสิทธิ์แบบหลายปัจจัยทาง SMS ให้กับแอป iOS ได้

การรับรองความถูกต้องแบบหลายปัจจัยช่วยเพิ่มความปลอดภัยของแอปของคุณ แม้ว่าผู้โจมตีมักจะบุกรุกรหัสผ่านและบัญชีโซเชียล แต่การสกัดกั้นข้อความนั้นยากกว่า

ก่อนที่คุณจะเริ่ม

  1. เปิดใช้งานผู้ให้บริการอย่างน้อยหนึ่งรายที่รองรับการรับรองความถูกต้องแบบหลายปัจจัย ผู้ให้บริการทุกรายรองรับ MFA ยกเว้น การตรวจสอบสิทธิ์ทางโทรศัพท์ การตรวจสอบแบบไม่เปิดเผยตัวตน และ Apple Game Center

  2. ตรวจสอบให้แน่ใจว่าแอปของคุณกำลังยืนยันอีเมลของผู้ใช้ MFA กำหนดให้มีการยืนยันอีเมล วิธีนี้จะป้องกันไม่ให้ผู้ไม่ประสงค์ดีลงทะเบียนใช้บริการด้วยอีเมลที่พวกเขาไม่ได้เป็นเจ้าของ จากนั้นจึงล็อกเจ้าของที่แท้จริงออกด้วยการเพิ่มปัจจัยที่สอง

การเปิดใช้งานการรับรองความถูกต้องแบบหลายปัจจัย

  1. เปิดหน้า การตรวจสอบสิทธิ์ > วิธีการลงชื่อเข้าใช้ ของคอนโซล Firebase

  2. ในส่วน ขั้นสูง ให้เปิดใช้งาน SMS Multi-factor Authentication

    คุณควรป้อนหมายเลขโทรศัพท์ที่จะใช้ทดสอบแอปด้วย แม้ว่าจะเป็นทางเลือก แต่ขอแนะนำอย่างยิ่งให้ลงทะเบียนหมายเลขโทรศัพท์ทดสอบเพื่อหลีกเลี่ยงการควบคุมปริมาณระหว่างการพัฒนา

  3. หากคุณยังไม่ได้อนุญาตโดเมนของแอปของคุณ ให้เพิ่มลงในรายการอนุญาตบนหน้า การตรวจสอบสิทธิ์ > การตั้งค่า ของคอนโซล Firebase

กำลังยืนยันแอปของคุณ

Firebase จำเป็นต้องยืนยันว่าคำขอ SMS มาจากแอปของคุณ คุณสามารถทำได้สองวิธี:

  • การแจ้งเตือน APN แบบไม่มีเสียง : เมื่อคุณลงชื่อเข้าใช้ผู้ใช้เป็นครั้งแรก Firebase จะสามารถส่งการแจ้งเตือนแบบพุชแบบไม่มีเสียงไปยังอุปกรณ์ของผู้ใช้ได้ การตรวจสอบสิทธิ์สามารถดำเนินการต่อได้หากแอปได้รับการแจ้งเตือน โปรดทราบว่าตั้งแต่ iOS 8.0 เป็นต้นไป คุณไม่จำเป็นต้องขอให้ผู้ใช้อนุญาตการแจ้งเตือนแบบพุชเพื่อใช้วิธีนี้

  • การยืนยัน reCAPTCHA : หากคุณไม่สามารถส่งการแจ้งเตือนแบบเงียบได้ (เช่น เนื่องจากผู้ใช้ปิดใช้งานการรีเฟรชพื้นหลัง หรือคุณกำลังทดสอบแอปของคุณในเครื่องจำลอง iOS) คุณสามารถใช้ reCAPTCHA ได้ ในหลายกรณี reCAPTCHA จะแก้ปัญหาเองโดยอัตโนมัติโดยที่ผู้ใช้ไม่ต้องดำเนินการใดๆ

การใช้การแจ้งเตือนแบบเงียบ

หากต้องการเปิดใช้งานการแจ้งเตือน APN เพื่อใช้กับ Firebase:

  1. ใน Xcode ให้เปิดใช้งานการแจ้งเตือนแบบพุช สำหรับโปรเจ็กต์ของคุณ

  2. อัปโหลดคีย์การตรวจสอบสิทธิ์ APN ของคุณโดยใช้คอนโซล Firebase (การเปลี่ยนแปลงของคุณจะถูกส่งต่อไปยัง Google Cloud Firebase โดยอัตโนมัติ) หากคุณยังไม่มีคีย์การตรวจสอบสิทธิ์ APN โปรดดู การกำหนดค่า APN ด้วย FCM เพื่อเรียนรู้วิธีการรับ

    1. เปิด คอนโซล Firebase

    2. นำทางไปยัง การตั้งค่าโครงการ

    3. เลือกแท็บ การส่งข้อความบนคลาวด์

    4. ใต้ คีย์การตรวจสอบสิทธิ์ APN ในส่วน การกำหนดค่าแอป iOS ให้คลิก อัปโหลด

    5. เลือกรหัสของคุณ

    6. เพิ่มรหัสคีย์สำหรับคีย์ คุณสามารถค้นหารหัสคีย์ได้ในส่วน ใบรับรอง ตัวระบุ และโปรไฟล์ ใน ศูนย์นักพัฒนา Apple

    7. คลิก อัปโหลด

หากคุณมีใบรับรอง APN อยู่แล้ว คุณสามารถอัปโหลดใบรับรองแทนได้

ใช้การยืนยัน reCAPTCHA

หากต้องการเปิดใช้งาน SDK ไคลเอ็นต์เพื่อใช้ reCAPTCHA:

  1. เปิดการกำหนดค่าโครงการของคุณใน Xcode

  2. ดับเบิลคลิกชื่อโครงการในมุมมองแผนผังด้านซ้าย

  3. เลือกแอปของคุณจากส่วน เป้าหมาย

  4. เลือกแท็บ ข้อมูล

  5. ขยายส่วน ประเภท URL

  6. คลิกปุ่ม +

  7. ป้อนรหัสไคลเอ็นต์ที่กลับรายการของคุณในฟิลด์ แบบแผน URL คุณจะพบค่านี้ที่แสดงอยู่ในไฟล์การกำหนดค่า GoogleService-Info.plist เป็น REVERSED_CLIENT_ID

เมื่อเสร็จแล้ว การกำหนดค่าของคุณควรมีลักษณะคล้ายกับต่อไปนี้:

รูปแบบที่กำหนดเอง

หรือคุณสามารถปรับแต่งวิธีที่แอปนำเสนอ SFSafariViewController หรือ UIWebView เมื่อแสดง reCAPTCHA ได้ เมื่อต้องการทำเช่นนี้ ให้สร้างคลาสแบบกำหนดเองที่สอดคล้องกับโปรโตคอล FIRAuthUIDelegate และส่งผ่านไปยัง verifyPhoneNumber:UIDelegate:completion:

การเลือกรูปแบบการลงทะเบียน

คุณสามารถเลือกได้ว่าแอปของคุณต้องมีการตรวจสอบสิทธิ์แบบหลายปัจจัยหรือไม่ รวมถึงจะลงทะเบียนผู้ใช้อย่างไรและเมื่อใด รูปแบบทั่วไปบางประการ ได้แก่:

  • ลงทะเบียนปัจจัยที่สองของผู้ใช้เป็นส่วนหนึ่งของการลงทะเบียน ใช้วิธีนี้หากแอปของคุณต้องมีการตรวจสอบสิทธิ์แบบหลายปัจจัยสำหรับผู้ใช้ทั้งหมด โปรดทราบว่าบัญชีต้องมีที่อยู่อีเมลที่ยืนยันแล้วจึงจะลงทะเบียนปัจจัยที่สองได้ ดังนั้นขั้นตอนการลงทะเบียนของคุณจะต้องรองรับสิ่งนี้

  • เสนอตัวเลือกที่ข้ามได้เพื่อลงทะเบียนปัจจัยที่ 2 ระหว่างการลงทะเบียน แอพที่ต้องการสนับสนุน แต่ไม่จำเป็นต้องมีการตรวจสอบสิทธิ์แบบหลายปัจจัยอาจชอบวิธีนี้

  • ให้ความสามารถในการเพิ่มปัจจัยที่สองจากบัญชีของผู้ใช้หรือหน้าการจัดการโปรไฟล์ แทนหน้าจอการลงทะเบียน สิ่งนี้จะช่วยลดความขัดแย้งระหว่างขั้นตอนการลงทะเบียน ในขณะที่ยังคงให้การรับรองความถูกต้องแบบหลายปัจจัยสำหรับผู้ใช้ที่คำนึงถึงความปลอดภัย

  • ต้องเพิ่มปัจจัยที่สองทีละน้อยเมื่อผู้ใช้ต้องการเข้าถึงคุณลักษณะที่มีข้อกำหนดด้านความปลอดภัยที่เพิ่มขึ้น

การลงทะเบียนปัจจัยที่สอง

หากต้องการลงทะเบียนปัจจัยรองใหม่สำหรับผู้ใช้:

  1. ตรวจสอบสิทธิ์ผู้ใช้อีกครั้ง

  2. ขอให้ผู้ใช้ป้อนหมายเลขโทรศัพท์ของตน

  3. รับเซสชันแบบหลายปัจจัยสำหรับผู้ใช้:

    สวิฟท์

    authResult.user.multiFactor.getSessionWithCompletion() { (session, error) in
      // ...
    }
    

    วัตถุประสงค์-C

    [authResult.user.multiFactor
      getSessionWithCompletion:^(FIRMultiFactorSession * _Nullable session,
                                NSError * _Nullable error) {
        // ...
    }];
    
  4. ส่งข้อความยืนยันไปยังโทรศัพท์ของผู้ใช้ ตรวจสอบให้แน่ใจว่าหมายเลขโทรศัพท์อยู่ในรูปแบบที่มีเครื่องหมาย + นำหน้า และไม่มีเครื่องหมายวรรคตอนหรือช่องว่างอื่นๆ (เช่น +15105551234 )

    สวิฟท์

    // 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.
    }];
    

    แม้ว่าจะไม่จำเป็น แต่แนวทางปฏิบัติที่ดีที่สุดคือแจ้งให้ผู้ใช้ทราบล่วงหน้าว่าพวกเขาจะได้รับข้อความ SMS และใช้อัตรามาตรฐานดังกล่าว

    เมธอด verifyPhoneNumber() เริ่มกระบวนการตรวจสอบแอปในเบื้องหลังโดยใช้การแจ้งเตือนแบบพุชแบบเงียบ หากไม่มีการแจ้งเตือนแบบพุช ระบบจะออกคำถาม reCAPTCHA แทน

  5. เมื่อส่งรหัส SMS แล้ว ขอให้ผู้ใช้ยืนยันรหัส จากนั้นใช้การตอบสนองเพื่อสร้าง PhoneAuthCredential :

    สวิฟท์

    // 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];
    
  6. เริ่มต้นวัตถุการยืนยัน:

    สวิฟท์

    let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
    

    วัตถุประสงค์-C

    FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
    
  7. เสร็จสิ้นการลงทะเบียน หรือคุณสามารถระบุชื่อที่แสดงสำหรับปัจจัยที่สองได้ สิ่งนี้มีประโยชน์สำหรับผู้ใช้ที่มีปัจจัยวินาทีหลายตัว เนื่องจากหมายเลขโทรศัพท์ถูกปกปิดในระหว่างขั้นตอนการตรวจสอบสิทธิ์ (เช่น +1******1234)

    สวิฟท์

    // 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) {
        // ...
    }];
    

รหัสด้านล่างแสดงตัวอย่างที่สมบูรณ์ของการลงทะเบียนปัจจัยที่สอง:

สวิฟท์

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) {
            // ...
        }];
    }];
}];

ยินดีด้วย! คุณลงทะเบียนปัจจัยการรับรองความถูกต้องที่สองสำหรับผู้ใช้สำเร็จแล้ว

การลงชื่อเข้าใช้ผู้ใช้ด้วยปัจจัยที่ 2

หากต้องการลงชื่อเข้าใช้ผู้ใช้ด้วยการยืนยัน SMS แบบสองปัจจัย:

  1. ลงชื่อเข้าใช้ผู้ใช้ด้วยปัจจัยแรก จากนั้นตรวจพบข้อผิดพลาดที่ระบุว่าจำเป็นต้องมีการตรวจสอบสิทธิ์แบบหลายปัจจัย ข้อผิดพลาดนี้มีตัวแก้ไข คำแนะนำเกี่ยวกับปัจจัยที่สองที่ลงทะเบียน และเซสชันพื้นฐานที่พิสูจน์ว่าผู้ใช้ตรวจสอบสิทธิ์ด้วยปัจจัยแรกได้สำเร็จ

    ตัวอย่างเช่น หากปัจจัยแรกของผู้ใช้คืออีเมลและรหัสผ่าน:

    สวิฟท์

    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()

  2. หากผู้ใช้มีปัจจัยรองหลายรายการที่ลงทะเบียนไว้ ให้ถามผู้ใช้ว่าควรใช้ปัจจัยใด คุณสามารถรับหมายเลขโทรศัพท์ที่มาสก์ได้ด้วย resolver.hints[selectedIndex].phoneNumber และชื่อที่แสดงด้วย resolver.hints[selectedIndex].displayName

    สวิฟท์

    // 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.
    }
    
  3. ส่งข้อความยืนยันไปยังโทรศัพท์ของผู้ใช้:

    สวิฟท์

    // 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.
        }
    }];
    
  4. เมื่อส่งรหัส SMS แล้ว ขอให้ผู้ใช้ตรวจสอบรหัสและใช้เพื่อสร้าง PhoneAuthCredential :

    สวิฟท์

    // 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];
    
  5. เริ่มต้นวัตถุยืนยันด้วยหนังสือรับรอง:

    สวิฟท์

    let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
    

    วัตถุประสงค์-C

    FIRMultiFactorAssertion *assertion =
        [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
    
  6. แก้ไขปัญหาการลงชื่อเข้าใช้ จากนั้นคุณจึงสามารถเข้าถึงผลการลงชื่อเข้าใช้เดิมได้ ซึ่งรวมถึงข้อมูลเฉพาะของผู้ให้บริการมาตรฐานและข้อมูลประจำตัวการตรวจสอบสิทธิ์:

    สวิฟท์

    // 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.
        }
    }];
    

โค้ดด้านล่างแสดงตัวอย่างที่สมบูรณ์ของการลงชื่อเข้าใช้ผู้ใช้แบบหลายปัจจัย:

สวิฟท์

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.
                }
            }];
        }];
    }
}];

ยินดีด้วย! คุณลงชื่อเข้าใช้ผู้ใช้โดยใช้การรับรองความถูกต้องแบบหลายปัจจัยสำเร็จแล้ว

อะไรต่อไป