การตรวจสอบสิทธิ์ทางโทรศัพท์

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

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

Firebase Phone Authentication ไม่รองรับในบางประเทศ โปรดดูข้อมูลเพิ่มเติมในคำถามที่พบบ่อย

ตั้งค่า

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

  1. ในคอนโซล Firebase ให้ไปที่ความปลอดภัย > การตรวจสอบสิทธิ์

  2. ในแท็บวิธีการลงชื่อเข้าใช้ ให้เปิดใช้ผู้ให้บริการการลงชื่อเข้าใช้โทรศัพท์

  3. ตั้งค่าข้อกำหนดเฉพาะแพลตฟอร์ม

    • iOS+: ใน Xcode ให้เปิดใช้ข้อความ Push สำหรับโปรเจ็กต์และตรวจสอบว่าได้กำหนดค่าคีย์การตรวจสอบสิทธิ์ APNs ด้วย Firebase Cloud Messaging (FCM) แล้ว นอกจากนี้ คุณต้อง เปิดใช้โหมดเบื้องหลัง สำหรับการแจ้งเตือนระยะไกล

      หากต้องการดูคำอธิบายโดยละเอียดเกี่ยวกับขั้นตอนนี้ โปรดดูเอกสารประกอบ Firebase iOS Phone Auth

    • Android: หากยังไม่ได้ทำ ให้ระบุลายนิ้วมือ SHA-1 ของแอปโดยทำดังนี้

      1. ในคอนโซล Firebase ให้ไปที่ การตั้งค่า > ทั่วไป แท็บ

      2. เลื่อนลงไปที่การ์ดแอปของคุณ เลือกแอป Android แล้วเพิ่มลายนิ้วมือ SHA-1 ในช่องลายนิ้วมือใบรับรอง SHA

      ดูรายละเอียดเกี่ยวกับวิธีรับลายนิ้วมือ SHA ของแอปได้ที่การตรวจสอบสิทธิ์ไคลเอ็นต์

    • เว็บ: หากยังไม่ได้ทำ ให้ให้สิทธิ์โดเมนของแอปโดยทำดังนี้

      1. ในคอนโซลFirebase ให้ไปที่แท็บ ความปลอดภัย> การตรวจสอบสิทธิ์ > การตั้งค่า

      2. ในส่วนโดเมนที่ได้รับอนุญาต ให้คลิกเพิ่มโดเมน แล้วเพิ่ม โดเมน

การใช้งาน

Firebase Authentication SDK สำหรับ Flutter มี 2 วิธีในการลงชื่อเข้าใช้ของผู้ใช้ด้วยหมายเลขโทรศัพท์ แพลตฟอร์มเนทีฟ (เช่น Android และ iOS) มีฟังก์ชันการทำงานที่แตกต่างจากเว็บในการตรวจสอบหมายเลขโทรศัพท์ ดังนั้นจึงมี 2 วิธีสำหรับแต่ละแพลตฟอร์มโดยเฉพาะ ดังนี้

  • แพลตฟอร์มเนทีฟ: verifyPhoneNumber.
  • แพลตฟอร์มเว็บ: signInWithPhoneNumber.

เนทีฟ: verifyPhoneNumber

ในแพลตฟอร์มเนทีฟ ระบบจะต้องยืนยันหมายเลขโทรศัพท์ของผู้ใช้ก่อน จากนั้นผู้ใช้จะลงชื่อเข้าใช้หรือลิงก์บัญชีกับ PhoneAuthCredential ได้

ขั้นแรก คุณต้องขอหมายเลขโทรศัพท์จากผู้ใช้ เมื่อได้รับหมายเลขโทรศัพท์แล้ว ให้เรียกใช้เมธอด verifyPhoneNumber()

await FirebaseAuth.instance.verifyPhoneNumber(
  phoneNumber: '+44 7123 123 456',
  verificationCompleted: (PhoneAuthCredential credential) {},
  verificationFailed: (FirebaseAuthException e) {},
  codeSent: (String verificationId, int? resendToken) {},
  codeAutoRetrievalTimeout: (String verificationId) {},
);

คุณต้องจัดการการเรียกกลับ 4 รายการแยกกัน ซึ่งแต่ละรายการจะกำหนดวิธีอัปเดต UI ของแอปพลิเคชัน

  1. verificationCompleted: การจัดการรหัส SMS โดยอัตโนมัติในอุปกรณ์ Android
  2. verificationFailed: จัดการเหตุการณ์ที่ล้มเหลว เช่น หมายเลขโทรศัพท์ไม่ถูกต้อง หรือเกินโควต้า SMS
  3. codeSent: จัดการเมื่อระบบส่งรหัสจาก Firebase ไปยังอุปกรณ์ ซึ่งใช้เพื่อแจ้งให้ผู้ใช้ป้อนรหัส
  4. codeAutoRetrievalTimeout: จัดการการหมดเวลาเมื่อการจัดการรหัส SMS อัตโนมัติล้มเหลว

verificationCompleted

ตัวจัดการนี้จะเรียกใช้ในอุปกรณ์ Android ที่รองรับการแก้ไขรหัส SMS อัตโนมัติเท่านั้น

เมื่อระบบส่งรหัส SMS ไปยังอุปกรณ์ Android จะยืนยันรหัส SMS โดยอัตโนมัติโดยไม่ต้องให้ผู้ใช้ป้อนรหัสด้วยตนเอง หากเกิดเหตุการณ์นี้ ระบบจะให้ PhoneAuthCredential โดยอัตโนมัติ ซึ่งสามารถใช้เพื่อลงชื่อเข้าใช้หรือลิงก์หมายเลขโทรศัพท์ของผู้ใช้ได้

FirebaseAuth auth = FirebaseAuth.instance;

await auth.verifyPhoneNumber(
  phoneNumber: '+44 7123 123 456',
  verificationCompleted: (PhoneAuthCredential credential) async {
    // ANDROID ONLY!

    // Sign the user in (or link) with the auto-generated credential
    await auth.signInWithCredential(credential);
  },
);

verificationFailed

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

FirebaseAuth auth = FirebaseAuth.instance;

await auth.verifyPhoneNumber(
  phoneNumber: '+44 7123 123 456',
  verificationFailed: (FirebaseAuthException e) {
    if (e.code == 'invalid-phone-number') {
      print('The provided phone number is not valid.');
    }

    // Handle other errors
  },
);

codeSent

เมื่อ Firebase ส่งรหัส SMS ไปยังอุปกรณ์ ตัวจัดการนี้จะทริกเกอร์ด้วย verificationId และ resendToken (resendToken รองรับในอุปกรณ์ Android เท่านั้น อุปกรณ์ iOS จะแสดงค่า null เสมอ)

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

FirebaseAuth auth = FirebaseAuth.instance;

await auth.verifyPhoneNumber(
  phoneNumber: '+44 7123 123 456',
  codeSent: (String verificationId, int? resendToken) async {
    // Update the UI - wait for the user to enter the SMS code
    String smsCode = 'xxxx';

    // Create a PhoneAuthCredential with the code
    PhoneAuthCredential credential = PhoneAuthProvider.credential(verificationId: verificationId, smsCode: smsCode);

    // Sign the user in (or link) with the credential
    await auth.signInWithCredential(credential);
  },
);

โดยค่าเริ่มต้น Firebase จะไม่ส่งข้อความ SMS ใหม่ซ้ำหากเพิ่งส่งไปเมื่อไม่นานมานี้ อย่างไรก็ตาม คุณสามารถลบล้างลักษณะการทำงานนี้ได้โดยเรียกใช้เมธอด verifyPhoneNumber อีกครั้งด้วยโทเค็นส่งซ้ำไปยังอาร์กิวเมนต์ forceResendingToken หากสำเร็จ ระบบจะส่งข้อความ SMS อีกครั้ง

codeAutoRetrievalTimeout

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

โดยค่าเริ่มต้น อุปกรณ์จะรอ 30 วินาที แต่คุณสามารถปรับแต่งระยะเวลารอได้ด้วยอาร์กิวเมนต์ timeout ดังนี้

FirebaseAuth auth = FirebaseAuth.instance;

await auth.verifyPhoneNumber(
  phoneNumber: '+44 7123 123 456',
  timeout: const Duration(seconds: 60),
  codeAutoRetrievalTimeout: (String verificationId) {
    // Auto-resolution timed out...
  },
);

เว็บ: signInWithPhoneNumber

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

Firebase Authentication SDK สำหรับ Flutter จะจัดการวิดเจ็ต reCAPTCHA โดยค่าเริ่มต้น แต่คุณสามารถควบคุมวิธีแสดงและกำหนดค่าวิดเจ็ตได้หากต้องการ หากต้องการเริ่มต้น ให้เรียกใช้เมธอด signInWithPhoneNumber ด้วยหมายเลขโทรศัพท์

FirebaseAuth auth = FirebaseAuth.instance;

// Wait for the user to complete the reCAPTCHA & for an SMS code to be sent.
ConfirmationResult confirmationResult = await auth.signInWithPhoneNumber('+44 7123 123 456');

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

UserCredential userCredential = await confirmationResult.confirm('123456');

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

การกำหนดค่า reCAPTCHA

วิดเจ็ต reCAPTCHA เป็นขั้นตอนที่จัดการอย่างเต็มรูปแบบซึ่งช่วยรักษาความปลอดภัยให้กับเว็บแอปพลิเคชัน

อาร์กิวเมนต์ที่ 2 ของ signInWithPhoneNumber รับอินสแตนซ์ RecaptchaVerifier ที่ไม่บังคับ ซึ่งสามารถใช้เพื่อจัดการวิดเจ็ตได้ โดยค่าเริ่มต้น วิดเจ็ตจะแสดงเป็นวิดเจ็ตที่มองไม่เห็นเมื่อทริกเกอร์ขั้นตอนการลงชื่อเข้าใช้ วิดเจ็ต "ที่มองไม่เห็น" จะปรากฏเป็นโมดัลแบบเต็มหน้าจอที่ด้านบนของแอปพลิเคชัน

อย่างไรก็ตาม คุณสามารถแสดงวิดเจ็ตแบบอินไลน์ที่ผู้ใช้ต้องกดอย่างชัดเจนเพื่อยืนยันตัวเองได้

หากต้องการเพิ่มวิดเจ็ตแบบอินไลน์ ให้ระบุรหัสองค์ประกอบ DOM ไปยังอาร์กิวเมนต์ container ของอินสแตนซ์ RecaptchaVerifier องค์ประกอบต้องมีอยู่และว่างเปล่า ไม่เช่นนั้นระบบจะแสดงข้อผิดพลาด หากไม่ได้ระบุอาร์กิวเมนต์ container วิดเจ็ตจะแสดงเป็น "มองไม่เห็น"

ConfirmationResult confirmationResult = await auth.signInWithPhoneNumber('+44 7123 123 456', RecaptchaVerifier(
  container: 'recaptcha',
  size: RecaptchaVerifierSize.compact,
  theme: RecaptchaVerifierTheme.dark,
));

คุณสามารถเปลี่ยนขนาดและธีมได้โดยปรับแต่งอาร์กิวเมนต์ size และ theme ตามที่แสดงด้านบน

นอกจากนี้ คุณยังสามารถฟังเหตุการณ์ต่างๆ ได้ เช่น ผู้ใช้ทำ reCAPTCHA เสร็จแล้วหรือไม่ reCAPTCHA หมดอายุแล้วหรือไม่ หรือเกิดข้อผิดพลาดขึ้นหรือไม่

RecaptchaVerifier(
  onSuccess: () => print('reCAPTCHA Completed!'),
  onError: (FirebaseAuthException error) => print(error),
  onExpired: () => print('reCAPTCHA Expired!'),
);

การทดสอบ

Firebase รองรับการทดสอบหมายเลขโทรศัพท์ในเครื่องโดยทำดังนี้

  1. ในคอนโซล Firebase ให้เลือกผู้ให้บริการการตรวจสอบสิทธิ์ "โทรศัพท์" แล้วคลิกเมนูแบบเลื่อนลง "หมายเลขโทรศัพท์สำหรับการทดสอบ"
  2. ป้อนหมายเลขโทรศัพท์ใหม่ (เช่น +44 7444 555666) และรหัสทดสอบ (เช่น 123456)

หากระบุหมายเลขโทรศัพท์ทดสอบให้กับเมธอด verifyPhoneNumber หรือ signInWithPhoneNumber ระบบจะไม่ส่ง SMS จริง แต่คุณสามารถระบุรหัสทดสอบให้กับ PhoneAuthProvider โดยตรงหรือใช้ตัวจัดการการตอบกลับผลการยืนยันของ signInWithPhoneNumber