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

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

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

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

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

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

  3. ติดตั้ง Firebase JavaScript SDK หากยังไม่ได้ทำ

    TOTP MFA ได้รับการสนับสนุนใน SDK เว็บแบบแยกส่วนเวอร์ชัน v9.19.1 ขึ้นไปเท่านั้น

เปิดใช้ TOTP MFA

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

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

  1. ติดตั้ง Firebase Admin Node.js SDK หากยังไม่ได้ทำ

    ระบบรองรับ TOTP MFA ใน 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 จากหน้าต่างที่อยู่ติดกันได้ด้วย เพื่อรองรับการเลื่อนเวลาระหว่างแต่ละฝ่ายและเวลาที่มนุษย์ตอบสนอง

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

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

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

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

  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

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

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

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

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

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

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

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

    import {
        getAuth,
        getMultiFactorResolver,
        TotpMultiFactorGenerator,
    } from "firebase/auth";
    
  2. เรียก 1 ใน 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;
    }
    

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

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

หากผู้ใช้ได้ลงชื่อสมัครใช้ตัวเลือก 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
        );
    }
}

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