เพิ่มการตรวจสอบสิทธิ์แบบหลายปัจจัยของ TOTP ลงในเว็บแอป

หากอัปเกรดเป็น Firebase Authentication with Identity Platform คุณจะเพิ่มการตรวจสอบสิทธิ์แบบหลายปัจจัย (MFA) โดยใช้รหัสผ่านที่สามารถใช้งานได้เพียงครั้งเดียวตามเวลา (TOTP) ลงในแอปได้

Firebase Authentication with Identity Platform ช่วยให้คุณใช้ TOTP เป็นปัจจัยเพิ่มเติมสำหรับการ MFA ได้ เมื่อ เปิดใช้ฟีเจอร์นี้ ผู้ใช้ที่พยายามลงชื่อเข้าใช้แอปจะเห็นคำขอ TOTP หากต้องการสร้างรหัส ผู้ใช้ต้องใช้แอป Authenticator ที่สร้างรหัส TOTP ที่ถูกต้องได้ เช่น Google Authenticator

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

  1. เปิดใช้ผู้ให้บริการที่รองรับ MFA อย่างน้อย 1 ราย โปรดทราบว่าผู้ให้บริการทั้งหมด ยกเว้นผู้ให้บริการต่อไปนี้รองรับ MFA

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

  3. หากยังไม่ได้ดำเนินการ ให้ติดตั้ง Firebase JavaScript SDK

    MFA แบบ TOTP รองรับเฉพาะใน Web SDK แบบโมดูลาร์ เวอร์ชัน v9.19.1 ขึ้นไป

เปิดใช้ MFA แบบ TOTP

หากต้องการเปิดใช้ TOTP เป็นปัจจัยที่ 2 ให้ใช้ Admin SDK หรือเรียกใช้ปลายทาง REST ของการกำหนดค่าโปรเจ็กต์

หากต้องการใช้ Admin SDK ให้ทำดังนี้

  1. หากยังไม่ได้ดำเนินการ โปรดติดตั้ง Firebase Admin Node.js SDK

    MFA แบบ TOTP รองรับเฉพาะใน Firebase Admin Node.js SDK เวอร์ชัน 11.6.0 ขึ้นไป

  2. เรียกใช้คำสั่งต่อไปนี้

    import { getAuth } from 'firebase-admin/auth';
    
    getAuth().projectConfigManager().updateProjectConfig(
    {
          multiFactorConfig: {
              providerConfigs: [{
                  state: "ENABLED",
                  totpProviderConfig: {
                      adjacentIntervals: NUM_ADJ_INTERVALS
                  }
              }]
          }
    })
    

    แทนที่ค่าต่อไปนี้

    • NUM_ADJ_INTERVALS: จำนวนช่วงเวลาที่อยู่ติดกัน ซึ่งจะยอมรับ TOTP โดยมีค่าตั้งแต่ 0 ถึง 10 ค่าเริ่มต้นคือ 5

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

หากต้องการเปิดใช้ MFA แบบ TOTP โดยใช้ REST API ให้เรียกใช้คำสั่งต่อไปนี้

curl -X PATCH "https://identitytoolkit.googleapis.com/admin/v2/projects/PROJECT_ID/config?updateMask=mfa" \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    -H "Content-Type: application/json" \
    -H "X-Goog-User-Project: PROJECT_ID" \
    -d \
    '{
        "mfa": {
          "providerConfigs": [{
            "state": "ENABLED",
            "totpProviderConfig": {
              "adjacentIntervals": NUM_ADJ_INTERVALS
            }
          }]
       }
    }'

แทนที่ค่าต่อไปนี้

  • PROJECT_ID: รหัสโปรเจ็กต์
  • NUM_ADJ_INTERVALS: จำนวนช่วงหน้าต่างเวลา ตั้งแต่ 0 ถึง 10 ค่าเริ่มต้นคือ 5

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

เลือกรูปแบบการลงทะเบียน

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

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

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

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

  • กำหนดให้เพิ่มปัจจัยที่ 2 ทีละรายการเมื่อผู้ใช้ต้องการเข้าถึง ฟีเจอร์ที่มีข้อกำหนดด้านความปลอดภัยที่เพิ่มขึ้น

ลงทะเบียนผู้ใช้ใน MFA แบบ TOTP

หลังจากเปิดใช้ MFA แบบ TOTP เป็นปัจจัยที่ 2 สำหรับแอปแล้ว ให้ใช้ตรรกะฝั่งไคลเอ็นต์ เพื่อลงทะเบียนผู้ใช้ใน MFA แบบ TOTP โดยทำดังนี้

  1. นำเข้าคลาสและฟังก์ชัน MFA ที่จำเป็น

    import {
      multiFactor,
      TotpMultiFactorGenerator,
      TotpSecret,
      getAuth,
    } from "firebase/auth";
    
  2. ตรวจสอบสิทธิ์ผู้ใช้อีกครั้ง

  3. สร้างข้อมูลลับ TOTP สำหรับผู้ใช้ที่ได้รับการตรวจสอบสิทธิ์

    // Generate a TOTP secret.
    const multiFactorSession = await multiFactor(currentUser).getSession();
    const totpSecret = await TotpMultiFactorGenerator.generateSecret(
      multiFactorSession
    );
    
  4. แสดงรหัสลับต่อผู้ใช้และแจ้งให้ผู้ใช้ป้อนรหัสลับลงในแอป Authenticator

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

    const totpUri = totpSecret.generateQrCodeUrl(
        currentUser.email,
        "Your App's Name"
    );
    await QRExampleLib.toCanvas(totpUri, qrElement);
    

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

    // Also display this key:
    const secret = totpSecret.secretKey;
    

    หลังจากผู้ใช้เพิ่มข้อมูลลับลงในแอป Authenticator แล้ว แอปจะเริ่มสร้าง TOTP

  5. แจ้งให้ผู้ใช้พิมพ์ TOTP ที่แสดงในแอป Authenticator และ ใช้เพื่อลงทะเบียน MFA ให้เสร็จสมบูรณ์

    // Ask the user for a verification code from the authenticator app.
    const verificationCode = // Code from user input.
    
    // Finalize the enrollment.
    const multiFactorAssertion = TotpMultiFactorGenerator.assertionForEnrollment(
      totpSecret,
      verificationCode
    );
    await multiFactor(currentUser).enroll(multiFactorAssertion, mfaDisplayName);
    

ลงชื่อเข้าใช้ผู้ใช้ด้วยปัจจัยที่สอง

หากต้องการลงชื่อเข้าใช้ผู้ใช้ด้วย TOTP MFA ให้ใช้โค้ดต่อไปนี้

  1. นำเข้าคลาสและฟังก์ชัน MFA ที่จำเป็น

    import {
        getAuth,
        getMultiFactorResolver,
        TotpMultiFactorGenerator,
    } from "firebase/auth";
    
  2. โทรหาวิธีการsignInWithวิธีใดวิธีหนึ่งเหมือนกับที่คุณทำหากไม่ได้ใช้ MFA (เช่น signInWithEmailAndPassword()) หากเมธอดแสดงข้อผิดพลาด auth/multi-factor-auth-required ให้เริ่มขั้นตอน MFA ของแอป

    try {
        const userCredential = await signInWithEmailAndPassword(
            getAuth(),
            email,
            password
        );
        // If the user is not enrolled with a second factor and provided valid
        // credentials, sign-in succeeds.
    
        // (If your app requires MFA, this could be considered an error
        // condition, which you would resolve by forcing the user to enroll a
        // second factor.)
    
        // ...
    } catch (error) {
        switch (error.code) {
            case "auth/multi-factor-auth-required":
                // Initiate your second factor sign-in flow. (See next step.)
                // ...
                break;
            case ...:  // Handle other errors, such as wrong passwords.
                break;
        }
    }
    
  3. โฟลว์ MFA ของแอปควรกระตุ้นให้ผู้ใช้เลือกปัจจัยที่ 2 ที่ต้องการใช้ก่อน คุณดูรายการปัจจัยที่ 2 ที่รองรับได้โดย ตรวจสอบพร็อพเพอร์ตี้ hints ของอินสแตนซ์ MultiFactorResolver ดังนี้

    const mfaResolver = getMultiFactorResolver(getAuth(), error);
    const enrolledFactors = mfaResolver.hints.map(info => info.displayName);
    
  4. หากผู้ใช้เลือกใช้ TOTP ให้แจ้งให้ผู้ใช้พิมพ์ TOTP ที่แสดงในแอป Authenticator และใช้เพื่อลงชื่อเข้าใช้

    switch (mfaResolver.hints[selectedIndex].factorId) {
        case TotpMultiFactorGenerator.FACTOR_ID:
            const otpFromAuthenticator = // OTP typed by the user.
            const multiFactorAssertion =
                TotpMultiFactorGenerator.assertionForSignIn(
                    mfaResolver.hints[selectedIndex].uid,
                    otpFromAuthenticator
                );
            try {
                const userCredential = await mfaResolver.resolveSignIn(
                    multiFactorAssertion
                );
                // Successfully signed in!
            } catch (error) {
                // Invalid or expired OTP.
            }
            break;
        case PhoneMultiFactorGenerator.FACTOR_ID:
            // Handle SMS second factor.
            break;
        default:
            // Unsupported second factor?
            break;
    }
    

ยกเลิกการลงทะเบียน MFA แบบ TOTP

ส่วนนี้อธิบายวิธีจัดการเมื่อผู้ใช้ยกเลิกการลงทะเบียน MFA แบบ TOTP

หากผู้ใช้ลงชื่อสมัครใช้ตัวเลือก MFA หลายรายการ และหากยกเลิกการลงทะเบียน จากตัวเลือกที่เปิดใช้ล่าสุด ผู้ใช้จะได้รับ auth/user-token-expired และออกจากระบบ ผู้ใช้ต้องลงชื่อเข้าใช้อีกครั้งและยืนยันข้อมูลเข้าสู่ระบบที่มีอยู่ เช่น อีเมลและรหัสผ่าน

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

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

try {
    // Unenroll from TOTP MFA.
    await multiFactor(currentUser).unenroll(mfaEnrollmentId);
} catch  (error) {
    if (error.code === 'auth/user-token-expired') {
        // If the user was signed out, re-authenticate them.

        // For example, if they signed in with a password, prompt them to
        // provide it again, then call `reauthenticateWithCredential()` as shown
        // below.

        const credential = EmailAuthProvider.credential(email, password);
        await reauthenticateWithCredential(
            currentUser,
            credential
        );
    }
}

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