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

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

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

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

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

คัดลอกข้อมูลโค้ดการเริ่มต้นจาก Firebase คอนโซลไปยังโครงการของคุณตามที่อธิบายไว้ใน เพิ่ม Firebase ลงในโปรเจ็กต์ JavaScript

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

  1. ในคอนโซล Firebase ให้เปิดส่วน Auth
  2. ในแท็บวิธีการลงชื่อเข้าใช้ ให้เปิดใช้ผู้ให้บริการอีเมล/รหัสผ่าน หมายเหตุ ต้องเปิดใช้การลงชื่อเข้าใช้อีเมล/รหัสผ่านเพื่อใช้การลงชื่อเข้าใช้ลิงก์อีเมล
  3. ในส่วนเดียวกัน ให้เปิดใช้การลงชื่อเข้าใช้ลิงก์อีเมล (การลงชื่อเข้าใช้แบบไม่ต้องใช้รหัสผ่าน)
  4. คลิกบันทึก

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

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

    • url: Deep Link ที่จะฝังและสถานะเพิ่มเติมที่จะส่งต่อ ต้องเพิ่มโดเมนของลิงก์ในรายการคอนโซล Firebase ของ โดเมนที่ได้รับอนุญาต ซึ่งสามารถค้นหาได้โดยไปที่แท็บวิธีการลงชื่อเข้าใช้ (การตรวจสอบสิทธิ์ -> การตั้งค่า)
    • android และ ios: แอปที่จะใช้เมื่อเปิดลิงก์ลงชื่อเข้าใช้ใน อุปกรณ์ Android หรือ Apple ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธี กำหนดค่าลิงก์แบบไดนามิกของ Firebase เพื่อเปิดลิงก์การดำเนินการอีเมลผ่านแอปบนอุปกรณ์เคลื่อนที่
    • handleCodeInApp: ตั้งค่าเป็น "จริง" การลงชื่อเข้าใช้จะต้องเป็นแบบต่อไปนี้เสมอ ดำเนินการในแอป ซึ่งแตกต่างจากการดำเนินการอื่นๆ ทางอีเมลนอกกลุ่ม (รหัสผ่าน การรีเซ็ตและการยืนยันอีเมล) เพราะว่าเมื่อจบขั้นตอนแล้ว ผู้ใช้ต้องลงชื่อเข้าใช้และสถานะการตรวจสอบสิทธิ์ยังคงอยู่ใน แอปนั้น
    • dynamicLinkDomain: เมื่อมีการกำหนดโดเมนลิงก์แบบไดนามิกที่กำหนดเองหลายโดเมน สำหรับโปรเจ็กต์ ให้ระบุลิงก์ที่จะใช้เมื่อเปิดลิงก์ผ่าน แอปบนอุปกรณ์เคลื่อนที่ที่ระบุ (เช่น example.page.link) มิฉะนั้น โดเมนแรกจะถูกเลือกโดยอัตโนมัติ

      Web

      const actionCodeSettings = {
        // URL you want to redirect back to. The domain (www.example.com) for this
        // URL must be in the authorized domains list in the Firebase Console.
        url: 'https://www.example.com/finishSignUp?cartId=1234',
        // This must be true.
        handleCodeInApp: true,
        iOS: {
          bundleId: 'com.example.ios'
        },
        android: {
          packageName: 'com.example.android',
          installApp: true,
          minimumVersion: '12'
        },
        dynamicLinkDomain: 'example.page.link'
      };

      Web

      var actionCodeSettings = {
        // URL you want to redirect back to. The domain (www.example.com) for this
        // URL must be in the authorized domains list in the Firebase Console.
        url: 'https://www.example.com/finishSignUp?cartId=1234',
        // This must be true.
        handleCodeInApp: true,
        iOS: {
          bundleId: 'com.example.ios'
        },
        android: {
          packageName: 'com.example.android',
          installApp: true,
          minimumVersion: '12'
        },
        dynamicLinkDomain: 'example.page.link'
      };

    ดูข้อมูลเพิ่มเติมเกี่ยวกับ ActionCodeSettings ได้ที่ สถานะการส่งในการดำเนินการอีเมล

  2. ขออีเมลของผู้ใช้

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

    Web

    import { getAuth, sendSignInLinkToEmail } from "firebase/auth";
    
    const auth = getAuth();
    sendSignInLinkToEmail(auth, email, actionCodeSettings)
      .then(() => {
        // The link was successfully sent. Inform the user.
        // Save the email locally so you don't need to ask the user for it again
        // if they open the link on the same device.
        window.localStorage.setItem('emailForSignIn', email);
        // ...
      })
      .catch((error) => {
        const errorCode = error.code;
        const errorMessage = error.message;
        // ...
      });

    Web

    firebase.auth().sendSignInLinkToEmail(email, actionCodeSettings)
      .then(() => {
        // The link was successfully sent. Inform the user.
        // Save the email locally so you don't need to ask the user for it again
        // if they open the link on the same device.
        window.localStorage.setItem('emailForSignIn', email);
        // ...
      })
      .catch((error) => {
        var errorCode = error.code;
        var errorMessage = error.message;
        // ...
      });

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

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

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

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

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

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

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

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

Web

import { getAuth, isSignInWithEmailLink, signInWithEmailLink } from "firebase/auth";

// Confirm the link is a sign-in with email link.
const auth = getAuth();
if (isSignInWithEmailLink(auth, window.location.href)) {
  // Additional state parameters can also be passed via URL.
  // This can be used to continue the user's intended action before triggering
  // the sign-in operation.
  // Get the email if available. This should be available if the user completes
  // the flow on the same device where they started it.
  let email = window.localStorage.getItem('emailForSignIn');
  if (!email) {
    // User opened the link on a different device. To prevent session fixation
    // attacks, ask the user to provide the associated email again. For example:
    email = window.prompt('Please provide your email for confirmation');
  }
  // The client SDK will parse the code from the link for you.
  signInWithEmailLink(auth, email, window.location.href)
    .then((result) => {
      // Clear email from storage.
      window.localStorage.removeItem('emailForSignIn');
      // You can access the new user by importing getAdditionalUserInfo
      // and calling it with result:
      // getAdditionalUserInfo(result)
      // You can access the user's profile via:
      // getAdditionalUserInfo(result)?.profile
      // You can check if the user is new or existing:
      // getAdditionalUserInfo(result)?.isNewUser
    })
    .catch((error) => {
      // Some error occurred, you can inspect the code: error.code
      // Common errors could be invalid email and invalid or expired OTPs.
    });
}

Web

// Confirm the link is a sign-in with email link.
if (firebase.auth().isSignInWithEmailLink(window.location.href)) {
  // Additional state parameters can also be passed via URL.
  // This can be used to continue the user's intended action before triggering
  // the sign-in operation.
  // Get the email if available. This should be available if the user completes
  // the flow on the same device where they started it.
  var email = window.localStorage.getItem('emailForSignIn');
  if (!email) {
    // User opened the link on a different device. To prevent session fixation
    // attacks, ask the user to provide the associated email again. For example:
    email = window.prompt('Please provide your email for confirmation');
  }
  // The client SDK will parse the code from the link for you.
  firebase.auth().signInWithEmailLink(email, window.location.href)
    .then((result) => {
      // Clear email from storage.
      window.localStorage.removeItem('emailForSignIn');
      // You can access the new user via result.user
      // Additional user info profile not available via:
      // result.additionalUserInfo.profile == null
      // You can check if the user is new or existing:
      // result.additionalUserInfo.isNewUser
    })
    .catch((error) => {
      // Some error occurred, you can inspect the code: error.code
      // Common errors could be invalid email and invalid or expired OTPs.
    });
}

การลงชื่อเข้าใช้ในแอปบนอุปกรณ์เคลื่อนที่ให้เสร็จสมบูรณ์

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

ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีจัดการการลงชื่อเข้าใช้ด้วยลิงก์อีเมลใน Android โปรดดูคู่มือ Android

ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีจัดการการลงชื่อเข้าใช้ด้วยลิงก์อีเมลใน Apple โปรดดูคู่มือแพลตฟอร์ม Apple

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

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

Web

import { getAuth, linkWithCredential, EmailAuthProvider } from "firebase/auth";

// Construct the email link credential from the current URL.
const credential = EmailAuthProvider.credentialWithLink(
  email, window.location.href);

// Link the credential to the current user.
const auth = getAuth();
linkWithCredential(auth.currentUser, credential)
  .then((usercred) => {
    // The provider is now successfully linked.
    // The phone user can now sign in with their phone number or email.
  })
  .catch((error) => {
    // Some error occurred.
  });

Web

// Construct the email link credential from the current URL.
var credential = firebase.auth.EmailAuthProvider.credentialWithLink(
  email, window.location.href);

// Link the credential to the current user.
firebase.auth().currentUser.linkWithCredential(credential)
  .then((usercred) => {
    // The provider is now successfully linked.
    // The phone user can now sign in with their phone number or email.
  })
  .catch((error) => {
    // Some error occurred.
  });

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

Web

import { getAuth, reauthenticateWithCredential, EmailAuthProvider } from "firebase/auth";

// Construct the email link credential from the current URL.
const credential = EmailAuthProvider.credentialWithLink(
  email, window.location.href);

// Re-authenticate the user with this credential.
const auth = getAuth();
reauthenticateWithCredential(auth.currentUser, credential)
  .then((usercred) => {
    // The user is now successfully re-authenticated and can execute sensitive
    // operations.
  })
  .catch((error) => {
    // Some error occurred.
  });

Web

// Construct the email link credential from the current URL.
var credential = firebase.auth.EmailAuthProvider.credentialWithLink(
  email, window.location.href);

// Re-authenticate the user with this credential.
firebase.auth().currentUser.reauthenticateWithCredential(credential)
  .then((usercred) => {
    // The user is now successfully re-authenticated and can execute sensitive
    // operations.
  })
  .catch((error) => {
    // Some error occurred.
  });

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

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

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

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

เทมเพลตอีเมลเริ่มต้นสำหรับการลงชื่อเข้าใช้ลิงก์

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

เทมเพลตนี้ใช้กับภาษาต่อไปนี้

รหัส ภาษา
AR อาหรับ
zh-CN จีน (ตัวย่อ)
zh-TW จีน (ดั้งเดิม)
nl ดัตช์
en อังกฤษ
en-GB อังกฤษ (สหราชอาณาจักร)
fr ฝรั่งเศส
de เยอรมัน
id อินโดนีเซีย
it อิตาลี
Ja ญี่ปุ่น
โค เกาหลี
pl โปแลนด์
PT-BR โปรตุเกส (บราซิล)
แต้ม โปรตุเกส (โปรตุเกส)
รู รัสเซีย
สเปน สเปน
ES_419 สเปน (ละตินอเมริกา)
th ไทย

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

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

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

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

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

หากต้องการนำผู้ใช้ออกจากระบบ โปรดโทร signOut

Web

import { getAuth, signOut } from "firebase/auth";

const auth = getAuth();
signOut(auth).then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});

Web

firebase.auth().signOut().then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});