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

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

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

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

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

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

  3. หากยังไม่ได้ติดตั้ง ให้ติดตั้ง Firebase Apple SDK

    MFA แบบ TOTP รองรับเฉพาะใน Apple SDK เวอร์ชัน v10.12.0 ขึ้นไป และใน iOS เท่านั้น

เปิดใช้ 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 วินาที ) ทั้ง 2 ฝ่ายจะสร้างรหัสผ่านเดียวกัน อย่างไรก็ตาม เพื่อให้สอดคล้องกับความคลาดเคลื่อนของนาฬิกา ระหว่างฝ่ายต่างๆ และเวลาตอบสนองของมนุษย์ คุณสามารถกำหนดค่าบริการ 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 วินาที ) ทั้ง 2 ฝ่ายจะสร้างรหัสผ่านเดียวกัน อย่างไรก็ตาม เพื่อให้สอดคล้องกับความคลาดเคลื่อนของนาฬิกา ระหว่างฝ่ายต่างๆ และเวลาตอบสนองของมนุษย์ คุณสามารถกำหนดค่าบริการ TOTP ให้ยอมรับ TOTP จากช่วงเวลาที่อยู่ติดกันได้ด้วย

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

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

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

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

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

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

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

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

  1. ตรวจสอบสิทธิ์ผู้ใช้อีกครั้ง

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

    // Generate a TOTP secret.
    guard let mfaSession = try? await currentUser.multiFactor.session() else { return }
    guard let totpSecret = try? await TOTPMultiFactorGenerator.generateSecret(with: mfaSession) else { return }
    
    // Display the secret to the user and prompt them to enter it into their
    // authenticator app. (See the next step.)
    
  3. แสดงรหัสลับต่อผู้ใช้และแจ้งให้ผู้ใช้ป้อนรหัสลับในแอปเครื่องมือตรวจสอบสิทธิ์

    // Display this key:
    let secret = totpSecret.sharedSecretKey()
    

    นอกเหนือจากการแสดงคีย์ลับแล้ว คุณยังพยายามเพิ่มคีย์ลับลงในแอปเครื่องมือตรวจสอบสิทธิ์เริ่มต้นของอุปกรณ์โดยอัตโนมัติได้ด้วย หากต้องการทำเช่นนั้น ให้สร้าง URI ของคีย์ที่เข้ากันได้กับ Google Authenticator แล้วส่งไปยัง openInOTPApp(withQRCodeURL:)

    let otpAuthUri = totpSecret.generateQRCodeURL(
        withAccountName: currentUser.email ?? "default account",
        issuer: "Your App Name")
    totpSecret.openInOTPApp(withQRCodeURL: otpAuthUri)
    

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

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

    // Ask the user for a verification code from the authenticator app.
    let verificationCode = // Code from user input.
    
    // Finalize the enrollment.
    let multiFactorAssertion = TOTPMultiFactorGenerator.assertionForEnrollment(
        with: totpSecret,
        oneTimePassword: verificationCode)
    do {
        try await currentUser.multiFactor.enroll(
            with: multiFactorAssertion,
            displayName: "TOTP")
    } catch {
        // Wrong or expired OTP. Re-prompt the user.
    }
    

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

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

  1. เรียกใช้เมธอด signIn(with...:)- เมธอดใดเมธอดหนึ่งเช่นเดียวกับที่คุณทำหากไม่ได้ใช้ MFA (เช่น signIn(withEmail:password:)) หากเมธอดแสดงข้อผิดพลาดที่มีรหัส secondFactorRequired ให้เริ่มขั้นตอน MFA ของแอป

    do {
        let authResult = try await Auth.auth().signIn(withEmail: email, password: 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 let error as AuthErrorCode where error.code == .secondFactorRequired {
        // Initiate your second factor sign-in flow. (See next step.)
        // ...
    } catch {
        // Other auth error.
        throw error
    }
    
  2. ขั้นตอน MFA ของแอปควรแจ้งให้ผู้ใช้เลือกปัจจัยที่ 2 ที่ต้องการใช้ก่อน คุณดูรายการปัจจัยที่ 2 ที่รองรับได้โดย ตรวจสอบพร็อพเพอร์ตี้ hints ของอินสแตนซ์ MultiFactorResolver

    let mfaKey = AuthErrorUserInfoMultiFactorResolverKey
    guard let resolver = error.userInfo[mfaKey] as? MultiFactorResolver else { return }
    let enrolledFactors = resolver.hints.map(\.displayName)
    
  3. หากผู้ใช้เลือกใช้ TOTP ให้แจ้งให้ผู้ใช้พิมพ์ TOTP ที่แสดงใน แอป Authenticator แล้วใช้เพื่อลงชื่อเข้าใช้

    let multiFactorInfo = resolver.hints[selectedIndex]
    switch multiFactorInfo.factorID {
    case TOTPMultiFactorID:
        let otpFromAuthenticator = // OTP typed by the user.
        let assertion = TOTPMultiFactorGenerator.assertionForSignIn(
            withEnrollmentID: multiFactorInfo.uid,
            oneTimePassword: otpFromAuthenticator)
        do {
            let authResult = try await resolver.resolveSignIn(with: assertion)
        } catch {
            // Wrong or expired OTP. Re-prompt the user.
        }
    default:
        return
    }
    

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

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

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

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

guard let currentUser = Auth.auth().currentUser else { return }

// Prompt the user to select a factor to unenroll, from this array:
currentUser.multiFactor.enrolledFactors

// ...

// Unenroll the second factor.
let multiFactorInfo = currentUser.multiFactor.enrolledFactors[selectedIndex]
do {
    try await currentUser.multiFactor.unenroll(with: multiFactorInfo)
} catch let error as AuthErrorCode where error.code == .invalidUserToken {
    // Second factor unenrolled, but the user was signed out. Re-authenticate
    // them.
}

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