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

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

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

การตรวจสอบสิทธิ์ทางโทรศัพท์ของ Firebase ไม่ได้รับการสนับสนุนในบางประเทศ โปรดดูคำถามที่พบบ่อยสำหรับข้อมูลเพิ่มเติม

ตั้งค่า

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

  1. เปิดใช้โทรศัพท์เป็นวิธีการลงชื่อเข้าใช้ในคอนโซล Firebase
  2. Android: หากคุณยังไม่ได้ตั้งค่าแฮช SHA-1 ของแอปในคอนโซล Firebase โปรดเปิดให้ดูข้อมูลเกี่ยวกับการค้นหาแฮช SHA-1 ของแอปที่การตรวจสอบสิทธิ์ไคลเอ็นต์
  3. iOS: ใน Xcode ให้เปิดใช้ข้อความ Push สําหรับโปรเจ็กต์ และตรวจสอบว่าคีย์การตรวจสอบสิทธิ์ APNs กําหนดค่าด้วย Firebase Cloud Messaging (FCM) นอกจากนี้ คุณต้องเปิดใช้โหมดพื้นหลังสำหรับการแจ้งเตือนระยะไกล หากต้องการดูคำอธิบายโดยละเอียดของขั้นตอนนี้ โปรดดูเอกสารการตรวจสอบสิทธิ์โทรศัพท์บน iOS ของ Firebase
  4. เว็บ: ตรวจสอบว่าได้เพิ่มโดเมนแอปพลิเคชันในคอนโซล Firebase ในส่วนโดเมนเปลี่ยนเส้นทาง OAuth แล้ว

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

การใช้งาน

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) {},
);

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

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

การยืนยันเสร็จสมบูรณ์

ระบบจะเรียกใช้เครื่องจัดการนี้เฉพาะในอุปกรณ์ 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);
  },
);

การยืนยันล้มเหลว

หาก 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
  },
);

ส่งรหัสแล้ว

เมื่อ 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 อีกครั้ง

codeAutoRetrievalระยะหมดเวลา

ในอุปกรณ์ 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 โดยตรงแทนได้