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

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

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

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

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

    • การตรวจสอบสิทธิ์ทางโทรศัพท์
    • การตรวจสอบสิทธิ์แบบไม่ระบุชื่อ
    • โทเค็นการตรวจสอบสิทธิ์ที่กำหนดเอง
    • Apple Game Center
  2. ตรวจสอบว่าแอปของคุณยืนยันอีเมลของผู้ใช้ การตรวจสอบสิทธิ์แบบหลายปัจจัยต้องมีการยืนยันอีเมล วิธีนี้จะช่วยป้องกันผู้ไม่ประสงค์ดีไม่ให้ลงทะเบียนใช้บริการด้วยอีเมลที่ไม่ได้เป็นเจ้าของ แล้วล็อกเจ้าของอีเมลตัวจริงออกด้วยการเพิ่มปัจจัยที่ 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 หากยังไม่ได้ดำเนินการ

    ฟีเจอร์นี้ใช้ได้กับ 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 จากหน้าการจัดการบัญชีหรือโปรไฟล์ของผู้ใช้แทนหน้าจอลงชื่อสมัครใช้ วิธีนี้ช่วยลดความยุ่งยากในกระบวนการลงทะเบียน ในขณะเดียวกันก็ยังคงมีการตรวจสอบสิทธิ์แบบหลายปัจจัยให้พร้อมใช้งานสำหรับผู้ใช้ที่ให้ความสำคัญกับความปลอดภัย

  • กำหนดให้เพิ่มปัจจัยที่ 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. แสดงรหัสลับให้ผู้ใช้เห็นและแจ้งให้ผู้ใช้ป้อนรหัสลับลงในแอปตรวจสอบสิทธิ์

    เมื่อใช้แอปตรวจสอบสิทธิ์หลายแอป ผู้ใช้จะเพิ่มข้อมูลลับ 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;
    

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

  5. แจ้งให้ผู้ใช้พิมพ์ TOTP ที่แสดงในแอปตรวจสอบสิทธิ์ แล้วใช้เพื่อลงทะเบียน 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);
    

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

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

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

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

    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 และใช้ TOTP ดังกล่าวเพื่อลงชื่อเข้าใช้

    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
        );
    }
}

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