Catch up on everything announced at Firebase Summit, and learn how Firebase can help you accelerate app development and run your app with confidence. Learn More

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

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

หากคุณอัปเกรดเป็น Firebase Authentication ด้วย Identity Platform คุณจะเพิ่ม SMS multi-factor authentication ลงในแอป iOS ได้

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

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

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

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

เปิดใช้งานการยืนยันตัวตนแบบหลายปัจจัย

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

  2. ในส่วน ขั้นสูง เปิดใช้งานการยืนยันตัวตนด้วย หลายปัจจัยทาง SMS

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

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

กำลังตรวจสอบแอปของคุณ

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

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

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

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

วิธีเปิดใช้งานการแจ้งเตือน APN สำหรับใช้กับ Firebase:

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

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

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

    2. ไปที่ การตั้งค่าโครงการ

    3. เลือกแท็บ Cloud Messaging

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

    5. เลือกคีย์ของคุณ

    6. เพิ่ม ID คีย์สำหรับคีย์ คุณสามารถค้นหา ID คีย์ได้ที่ใต้ Certificates, Identifiers & Profiles ใน Apple Developer Member Center

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

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

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

วิธีเปิดใช้งาน SDK ไคลเอ็นต์เพื่อใช้ reCAPTCHA:

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

  2. คลิกสองครั้งที่ชื่อโปรเจ็กต์ในมุมมองทรีด้านซ้าย

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

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

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

  6. คลิกปุ่ม +

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

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

โครงร่างที่กำหนดเอง

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

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

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

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

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

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

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

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

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

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

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

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

ในการลงชื่อเข้าใช้ผู้ใช้ด้วยการยืนยันทาง 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 {
      // Unsupported second factor.
      // Note that only phone second factors are currently supported.
    }
    

    วัตถุประสงค์-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 {
      // Unsupported second factor.
      // Note that only phone second factors are currently supported.
    }
    
  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.
                }
            }];
        }];
    }
}];

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

อะไรต่อไป