ตรวจสอบสิทธิ์ด้วย Firebase โดยใช้หมายเลขโทรศัพท์และ C++

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

เอกสารนี้อธิบายวิธีใช้ขั้นตอนการลงชื่อเข้าใช้ด้วยหมายเลขโทรศัพท์โดยใช้ Firebase SDK

ก่อนเริ่มต้น

  1. เพิ่ม Firebase ลงในโปรเจ็กต์ C++
  2. หากยังไม่ได้เชื่อมต่อแอปกับโปรเจ็กต์ Firebase ให้ดำเนินการจากคอนโซล Firebase
  3. ทำความเข้าใจข้อกำหนดของแพลตฟอร์มสำหรับการลงชื่อเข้าใช้ด้วยหมายเลขโทรศัพท์ ดังนี้
    • การลงชื่อเข้าใช้ด้วยหมายเลขโทรศัพท์ใช้ได้กับแพลตฟอร์มบนอุปกรณ์เคลื่อนที่เท่านั้น
    • ใน iOS การลงชื่อเข้าใช้ด้วยหมายเลขโทรศัพท์ต้องใช้อุปกรณ์จริงและจะใช้ไม่ได้ในเครื่องจำลอง

ข้อกังวลด้านความปลอดภัย

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

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

เปิดใช้การลงชื่อเข้าใช้ด้วยหมายเลขโทรศัพท์สำหรับโปรเจ็กต์ Firebase

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

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

เริ่มรับการแจ้งเตือน APN (แพลตฟอร์ม Apple)

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

วิธีเปิดใช้การแจ้งเตือน APNs เพื่อใช้กับ Firebase Authentication

  1. ใน Xcode ให้เปิดใช้ข้อความ Push สำหรับโปรเจ็กต์
  2. อัปโหลดใบรับรอง APNs ไปยัง Firebase หากยังไม่มีใบรับรอง APNs ให้สร้างใบรับรองใน Apple Developer Member Center

    1. ในคอนโซล Firebase ให้ไปที่ การตั้งค่า > ทั่วไป จากนั้นคลิกแท็บ Cloud Messaging
    2. คลิกอัปโหลดใบรับรองสำหรับใบรับรองการพัฒนา ใบรับรองเวอร์ชันที่ใช้งานจริง หรือทั้ง 2 อย่าง ทั้งนี้คุณต้องระบุอย่างน้อย 1 รายการ
    3. สำหรับใบรับรองแต่ละรายการ ให้เลือกไฟล์ .p12 และระบุรหัสผ่าน (หากมี) ตรวจสอบว่ารหัสชุดสำหรับใบรับรองนี้ตรงกับรหัสชุดของแอป คลิกบันทึก

ส่งรหัสยืนยันไปยังโทรศัพท์ของผู้ใช้

หากต้องการเริ่มการลงชื่อเข้าใช้ด้วยหมายเลขโทรศัพท์ ให้แสดงอินเทอร์เฟซที่แจ้งให้ผู้ใช้ระบุหมายเลขโทรศัพท์ แล้วเรียกใช้ PhoneAuthProvider::VerifyPhoneNumber เพื่อขอให้ Firebase ส่งรหัสการตรวจสอบสิทธิ์ไปยังโทรศัพท์ของผู้ใช้ทาง SMS ดังนี้

  1. รับหมายเลขโทรศัพท์ของผู้ใช้

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

  2. เรียกใช้ PhoneAuthProvider::VerifyPhoneNumber โดยส่งหมายเลขโทรศัพท์ของผู้ใช้ไปให้
    class PhoneListener : public PhoneAuthProvider::Listener {
     public:
      ~PhoneListener() override {}
    
      void OnVerificationCompleted(PhoneAuthCredential credential) override {
        // Auto-sms-retrieval or instant validation has succeeded (Android only).
        // There's no need for the end user to input the verification code manually.
        // `credential` can't be used instead of calling GetCredential().
      }
    
      void OnVerificationFailed(const std::string& error) override {
        // Verification code not sent.
      }
    
      void OnCodeSent(const std::string& verification_id,
                      const PhoneAuthProvider::ForceResendingToken&
                          force_resending_token) override {
        // Verification code successfully sent via SMS.
        // Show the Screen to enter the Code.
        // Developer may want to save that verification_id along with other app states in case
        // the app is terminated before the user gets the SMS verification code.
      }
    };
    
    PhoneListener phone_listener;
    PhoneAuhtOptions options;
    options.timeout_milliseconds = kAutoVerifyTimeOut;
    options.phone_number = phone_number;
    PhoneAuthProvider& phone_provider = PhoneAuthProvider::GetInstance(auth);
    phone_provider->VerifyPhoneNumber(options, &phone_listener);
    เมื่อคุณโทรหา PhoneAuthProvider::VerifyPhoneNumber, Firebase,
    • (ใน iOS) จะส่งข้อความ Push แบบไม่มีเสียงไปยังแอปของคุณ
    • ส่งข้อความ SMS ที่มีรหัสการตรวจสอบสิทธิ์ไปยังหมายเลขโทรศัพท์ที่ระบุ และส่งรหัสยืนยันไปยังฟังก์ชันการดำเนินการให้เสร็จสมบูรณ์ คุณจะต้องใช้ทั้งรหัสยืนยันและรหัสการยืนยันเพื่อลงชื่อเข้าใช้ให้ผู้ใช้
  3. บันทึกรหัสการยืนยันและกู้คืนเมื่อแอปโหลด การทำเช่นนี้จะช่วยให้มั่นใจได้ว่าคุณยังมีรหัสยืนยันที่ถูกต้องหากแอปถูกสิ้นสุดก่อนที่ผู้ใช้จะลงชื่อเข้าใช้เสร็จสมบูรณ์ (เช่น ขณะเปลี่ยนไปใช้แอป SMS)

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

หากการเรียกใช้ VerifyPhoneNumber ส่งผลให้มีการเรียกใช้ OnCodeSent ใน Listener คุณสามารถแจ้งให้ผู้ใช้พิมพ์รหัสยืนยันเมื่อได้รับในข้อความ SMS

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

ลงชื่อเข้าใช้ให้ผู้ใช้ด้วยรหัสยืนยัน

หลังจากที่ผู้ใช้ระบุรหัสยืนยันจาก SMS ให้กับแอปของคุณแล้ว ให้ลงชื่อเข้าใช้ให้ผู้ใช้โดยสร้างออบเจ็กต์ PhoneAuthCredential จากรหัสยืนยันและรหัสการยืนยัน แล้วส่งออบเจ็กต์นั้นไปยัง Auth::SignInWithCredential

  1. รับรหัสยืนยันจากผู้ใช้
  2. สร้างออบเจ็กต์ Credential จากรหัสยืนยันและรหัสการยืนยัน
    PhoneAuthCredential credential = phone_auth_provider->GetCredential(
        verification_id_.c_str(), verification_code.c_str());
        
  3. ลงชื่อเข้าใช้ผู้ใช้ด้วยออบเจ็กต์ Credential ดังนี้
    Future<User> future = auth_->SignInWithCredential(credential);
    future.OnCompletion(
        [](const Future<User*>& result, void*) {
          if (result.error() == kAuthErrorNone) {
            // Successful.
            // User is signed in.
            User user = *result.result();
    
            // This should display the phone number.
            printf("Phone number: %s", user.phone_number().c_str());
    
            // The phone number provider UID is the phone number itself.
            printf("Phone provider uid: %s", user.uid().c_str());
    
            // The phone number providerID is 'phone'
            printf("Phone provider ID: %s", user.provider_id().c_str());
          } else {
            // Error.
            printf("Sign in error: %s", result.error_message().c_str());
          }
        },
        nullptr);

ขั้นตอนถัดไป

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

  • ในแอป คุณสามารถรับข้อมูลโปรไฟล์พื้นฐานของผู้ใช้ได้จากออบเจ็กต์ firebase::auth::User ดังนี้

    firebase::auth::User user = auth->current_user();
    if (user.is_valid()) {
      std::string name = user.display_name();
      std::string email = user.email();
      std::string photo_url = user.photo_url();
      // The user's ID, unique to the Firebase project.
      // Do NOT use this value to authenticate with your backend server,
      // if you have one. Use firebase::auth::User::Token() instead.
      std::string uid = user.uid();
    }
  • ในกฎความปลอดภัยของ Firebase Realtime Database และ Cloud Storage คุณสามารถรับรหัสผู้ใช้ที่ไม่ซ้ำกันของผู้ใช้ที่ลงชื่อเข้าใช้จากตัวแปร auth และใช้เพื่อควบคุมข้อมูลที่ผู้ใช้เข้าถึงได้

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

หากต้องการนำผู้ใช้ออกจากระบบ ให้เรียกใช้ SignOut() ดังนี้

auth->SignOut();