ตรวจสอบสิทธิ์ด้วย Firebase โดยใช้ลิงก์อีเมล

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

การลงชื่อเข้าใช้ด้วยอีเมลมีประโยชน์มากมาย ดังนี้

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

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

  1. หากยังไม่ได้ทำ ให้ทำตามขั้นตอนในคู่มือเริ่มต้นใช้งาน

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

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

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

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

    3. ในส่วนเดียวกัน ให้เปิดใช้วิธีการลงชื่อเข้าใช้ด้วยลิงก์อีเมล (ลงชื่อเข้าใช้แบบไม่ต้องใช้รหัสผ่าน)

    4. คลิกบันทึก

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

  1. สร้างออบเจ็กต์ ActionCodeSettings ซึ่งจะให้คำแนะนำแก่ Firebase เกี่ยวกับวิธีสร้างลิงก์อีเมล ตั้งค่าฟิลด์ต่อไปนี้

    • url: Deep Link ที่จะฝังและสถานะเพิ่มเติมที่จะส่งต่อ เพิ่มโดเมนของลิงก์ลงในรายการโดเมนที่ได้รับอนุญาต หากยังไม่ได้เพิ่ม โดยทำดังนี้

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

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

      ลิงก์จะเปลี่ยนเส้นทางผู้ใช้ไปยัง URL นี้หากไม่ได้ติดตั้งแอปในอุปกรณ์ของผู้ใช้และติดตั้งแอปไม่ได้

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

    • handleCodeInApp: ตั้งค่าเป็น true การดำเนินการลงชื่อเข้าใช้ต้องดำเนินการให้เสร็จสมบูรณ์ในแอปเสมอ ซึ่งแตกต่างจากการดำเนินการทางอีเมลอื่นๆ นอกแอป (การรีเซ็ตรหัสผ่านและการยืนยันอีเมล) เนื่องจากในตอนท้ายของขั้นตอน ผู้ใช้จะต้องลงชื่อเข้าใช้และสถานะการตรวจสอบสิทธิ์จะยังคงอยู่ในแอป

    • dynamicLinkDomain: (เลิกใช้งานแล้ว ให้ใช้ linkDomain) เมื่อมีการกำหนดโดเมนลิงก์แบบไดนามิกที่กำหนดเองหลายโดเมนสำหรับโปรเจ็กต์ ให้ระบุโดเมนที่จะใช้เมื่อเปิดลิงก์โดยใช้แอปบนอุปกรณ์เคลื่อนที่ที่ระบุ (เช่น example.page.link) ไม่เช่นนั้นระบบจะเลือกโดเมนแรกโดยอัตโนมัติ

    • linkDomain: โดเมนโฮสติ้งของ Firebase ที่กำหนดเองซึ่งเลือกได้ที่จะใช้เมื่อเปิดลิงก์โดยใช้แอปบนอุปกรณ์เคลื่อนที่ที่ระบุ โดยโดเมนต้องได้รับการกำหนดค่าในโฮสติ้งของ Firebase และเป็นของโปรเจ็กต์ โดเมนนี้ต้องไม่ใช่โดเมนโฮสติ้งเริ่มต้น (web.app หรือ firebaseapp.com) และจะแทนที่การตั้งค่า dynamicLinkDomain ที่เลิกใช้งานแล้ว

    var acs = ActionCodeSettings(
        // URL you want to redirect back to. The domain (www.example.com) for this
        // URL must be whitelisted in the Firebase Console.
        url: 'https://www.example.com/finishSignUp?cartId=1234',
        // This must be true
        handleCodeInApp: true,
        iOSBundleId: 'com.example.ios',
        androidPackageName: 'com.example.android',
        // installIfNotAvailable
        androidInstallApp: true,
        // minimumVersion
        androidMinimumVersion: '12');
    
  2. ขออีเมลจากผู้ใช้

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

    var emailAuth = 'someemail@domain.com';
    FirebaseAuth.instance.sendSignInLinkToEmail(
            email: emailAuth, actionCodeSettings: acs)
        .catchError((onError) => print('Error sending email verification $onError'))
        .then((value) => print('Successfully sent email verification'));
    });
    

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

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

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

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

นอกจากนี้ โปรดตรวจสอบว่าคุณใช้ URL HTTPS ในสภาพแวดล้อมจริงเพื่อหลีกเลี่ยงไม่ให้เซิร์ฟเวอร์ตัวกลางดักจับลิงก์ของคุณ

ลงชื่อเข้าใช้ให้เสร็จสมบูรณ์

ระบบเลิกใช้งานลิงก์แบบไดนามิกของ Firebase แล้ว ตอนนี้ระบบจะใช้โฮสติ้งของ Firebase เพื่อส่งลิงก์การลงชื่อเข้าใช้ ทำตามคำแนะนำสำหรับการกำหนดค่าเฉพาะแพลตฟอร์ม ดังนี้

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

  1. ในตัวจัดการลิงก์ ให้ตรวจสอบว่าลิงก์มีไว้สำหรับการตรวจสอบสิทธิ์ด้วยลิงก์อีเมลหรือไม่ หากใช่ ให้ดำเนินการตามขั้นตอนการลงชื่อเข้าใช้ให้เสร็จสมบูรณ์

    // Confirm the link is a sign-in with email link.
    if (FirebaseAuth.instance.isSignInWithEmailLink(emailLink)) {
      try {
        // The client SDK will parse the code from the link for you.
        final userCredential = await FirebaseAuth.instance
            .signInWithEmailLink(email: emailAuth, emailLink: emailLink);
    
        // You can access the new user via userCredential.user.
        final emailAddress = userCredential.user?.email;
    
        print('Successfully signed in with email link!');
      } catch (error) {
        print('Error signing in with email link.');
      }
    }
    

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

ความแตกต่างจะอยู่ในครึ่งหลังของการดำเนินการ

final authCredential = EmailAuthProvider
    .credentialWithLink(email: emailAuth, emailLink: emailLink.toString());
try {
    await FirebaseAuth.instance.currentUser
        ?.linkWithCredential(authCredential);
} catch (error) {
    print("Error linking emailLink credential.");
}

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

final authCredential = EmailAuthProvider
    .credentialWithLink(email: emailAuth, emailLink: emailLink.toString());
try {
    await FirebaseAuth.instance.currentUser
        ?.reauthenticateWithCredential(authCredential);
} catch (error) {
    print("Error reauthenticating credential.");
}

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

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

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

ดูรายละเอียดเพิ่มเติมได้ในเอกสารประกอบเกี่ยวกับการป้องกันการแจกแจงอีเมล

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

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

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

ในกฎความปลอดภัยของฐานข้อมูลเรียลไทม์ของ Firebase และ Cloud Storage คุณสามารถรับรหัสผู้ใช้ที่ไม่ซ้ำกันของผู้ใช้ที่ลงชื่อเข้าใช้ได้จากตัวแปร auth และใช้รหัสนี้เพื่อควบคุมข้อมูลที่ผู้ใช้เข้าถึงได้

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

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

await FirebaseAuth.instance.signOut();