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

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

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

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

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

ใช้ Swift Package Manager เพื่อติดตั้งและจัดการทรัพยากร Dependency ของ Firebase

  1. เปิดโปรเจ็กต์แอปใน Xcode แล้วไปที่ไฟล์ > เพิ่มแพ็กเกจ
  2. เมื่อได้รับข้อความแจ้ง ให้เพิ่มที่เก็บ SDK สำหรับแพลตฟอร์ม Firebase ของ Apple ดังนี้
  3.   https://github.com/firebase/firebase-ios-sdk.git
  4. เลือกไลบรารีการตรวจสอบสิทธิ์ Firebase
  5. เพิ่มแฟล็ก -ObjC ลงในส่วนแฟล็ก Linker อื่นๆ ของการตั้งค่าบิลด์ของเป้าหมาย
  6. เมื่อเสร็จสิ้นแล้ว Xcode จะเริ่มแก้ปัญหาและดาวน์โหลดทรัพยากร Dependency ในเบื้องหลังโดยอัตโนมัติ

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

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

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

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

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

    Swift

    let actionCodeSettings = ActionCodeSettings()
    actionCodeSettings.url = URL(string: "https://www.example.com")
    // The sign-in operation has to always be completed in the app.
    actionCodeSettings.handleCodeInApp = true
    actionCodeSettings.setIOSBundleID(Bundle.main.bundleIdentifier!)
    actionCodeSettings.setAndroidPackageName("com.example.android",
                                             installIfNotAvailable: false, minimumVersion: "12")
    

    Objective-C

    FIRActionCodeSettings *actionCodeSettings = [[FIRActionCodeSettings alloc] init];
    [actionCodeSettings setURL:[NSURL URLWithString:@"https://www.example.com"]];
    // The sign-in operation has to always be completed in the app.
    actionCodeSettings.handleCodeInApp = YES;
    [actionCodeSettings setIOSBundleID:[[NSBundle mainBundle] bundleIdentifier]];
    [actionCodeSettings setAndroidPackageName:@"com.example.android"
                        installIfNotAvailable:NO
                               minimumVersion:@"12"];
    

    ดูข้อมูลเพิ่มเติมเกี่ยวกับ ActionCodeSettings ได้ที่ส่วน Passing State in Email Actions

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

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

    Swift

    Auth.auth().sendSignInLink(toEmail: email,
                               actionCodeSettings: actionCodeSettings) { error in
      // ...
        if let error = error {
          self.showMessagePrompt(error.localizedDescription)
          return
        }
        // 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.
        UserDefaults.standard.set(email, forKey: "Email")
        self.showMessagePrompt("Check your email for link")
        // ...
    }
    

    Objective-C

    [[FIRAuth auth] sendSignInLinkToEmail:email
                       actionCodeSettings:actionCodeSettings
                               completion:^(NSError *_Nullable error) {
      // ...
        if (error) {
          [self showMessagePrompt:error.localizedDescription];
           return;
        }
        // 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.
        [NSUserDefaults.standardUserDefaults setObject:email forKey:@"Email"];
        [self showMessagePrompt:@"Check your email for link"];
        // ...
    }];
    

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

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

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

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

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

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

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

  1. เปิดใช้ลิงก์แบบไดนามิกของ Firebase:

    1. ในคอนโซล Firebase ให้เปิดส่วนลิงก์แบบไดนามิก
    2. หากยังไม่ได้ยอมรับข้อกำหนดลิงก์แบบไดนามิกและสร้างโดเมนลิงก์แบบไดนามิก ให้ยอมรับเลย

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

      example.page.link

      คุณจะต้องใช้ค่านี้เมื่อกำหนดค่าแอป Apple หรือ Android ให้สกัดกั้นลิงก์ที่เข้ามา

  2. การกำหนดค่าแอปพลิเคชัน Apple

    1. หากคุณวางแผนที่จะจัดการลิงก์เหล่านี้จากแอปพลิเคชัน คุณจะต้องระบุรหัสแพ็กเกจในการตั้งค่าโปรเจ็กต์คอนโซล Firebase นอกจากนี้ คุณจะต้องระบุรหัส App Store และรหัสทีมนักพัฒนาซอฟต์แวร์ของ Apple ด้วย
    2. นอกจากนี้ คุณจะต้องกำหนดค่าโดเมนเครื่องจัดการการดำเนินการกับอีเมลเป็นโดเมนที่เชื่อมโยงในความสามารถของแอปพลิเคชัน โดยค่าเริ่มต้น เครื่องจัดการการดำเนินการกับอีเมลจะโฮสต์อยู่ในโดเมนตามตัวอย่างต่อไปนี้
      APP_ID.firebaseapp.com
    3. หากคุณวางแผนที่จะเผยแพร่แอปพลิเคชันไปยัง iOS เวอร์ชัน 8 และต่ำกว่า คุณจะต้องตั้งค่ารหัสชุดเป็นรูปแบบที่กำหนดเองสำหรับ URL ขาเข้า
    4. ดูข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้ได้ที่วิธีการรับลิงก์แบบไดนามิกสำหรับแพลตฟอร์ม Apple

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

Swift

if Auth.auth().isSignIn(withEmailLink: link) {
        Auth.auth().signIn(withEmail: email, link: self.link) { user, error in
          // ...
        }
}

Objective-C

if ([[FIRAuth auth] isSignInWithEmailLink:link]) {
    [[FIRAuth auth] signInWithEmail:email
                               link:link
                         completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) {
      // ...
    }];
}

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

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

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

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

Swift

  let credential = EmailAuthCredential.credential(withEmail:email
                                                       link:link)
  Auth.auth().currentUser?.link(with: credential) { authData, error in
    if (error) {
      // And error occurred during linking.
      return
    }
    // The provider was successfully linked.
    // The phone user can now sign in with their phone number or email.
  }

Objective-C

  FIRAuthCredential *credential =
      [FIREmailAuthProvider credentialWithEmail:email link:link];
  [FIRAuth auth].currentUser
      linkWithCredential:credential
              completion:^(FIRAuthDataResult *_Nullable result,
                           NSError *_Nullable error) {
    if (error) {
      // And error occurred during linking.
      return;
    }
    // The provider was successfully linked.
    // The phone user can now sign in with their phone number or email.
  }];

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

Swift

  let credential = EmailAuthProvider.credential(withEmail:email
                                                       link:link)
  Auth.auth().currentUser?.reauthenticate(with: credential) { authData, error in
    if (error) {
      // And error occurred during re-authentication.
      return
    }
    // The user was successfully re-authenticated.
  }

Objective-C

  FIRAuthCredential *credential =
      [FIREmailAuthCredential credentialWithEmail:email link:link];
  [FIRAuth auth].currentUser
      reauthenticateWithCredential:credential
                        completion:^(FIRAuthDataResult *_Nullable result,
                                     NSError *_Nullable error) {
    if (error) {
      // And error occurred during re-authentication
      return;
    }
    // The user was successfully re-authenticated.
  }];

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

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

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

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

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

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

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

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

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

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

Swift

let firebaseAuth = Auth.auth()
do {
  try firebaseAuth.signOut()
} catch let signOutError as NSError {
  print("Error signing out: %@", signOutError)
}

Objective-C

NSError *signOutError;
BOOL status = [[FIRAuth auth] signOut:&signOutError];
if (!status) {
  NSLog(@"Error signing out: %@", signOutError);
  return;
}

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