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

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

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

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

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

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

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

    ระบบรองรับ TOTP MFA ใน Android SDK เวอร์ชัน v22.1.0 ขึ้นไปเท่านั้น

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

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

เลือกลักษณะการลงทะเบียน

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

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

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

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

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

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

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

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

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

    // Generate a TOTP secret.
    Firebase.auth.currentUser.multiFactor.session
        .addOnSuccessListener { multiFactorSession ->
            TotpMultiFactorGenerator.generateSecret(multiFactorSession)
                .addOnSuccessListener { totpSecret ->
                    // Display the secret to the user and prompt them to
                    // enter it into their authenticator app. (See the next
                    // step.)
                }
        }
    
  3. แสดงข้อมูลลับให้ผู้ใช้เห็นและแจ้งให้ผู้ใช้ป้อนข้อมูลลับลงในแอป Authenticator

    // Display this key:
    val secret = totpSecret.sharedSecretKey
    

    นอกจากการแสดงคีย์ลับแล้ว คุณยังลองเพิ่มคีย์ลับลงในแอป Authenticator เริ่มต้นของอุปกรณ์โดยอัตโนมัติได้ด้วย โดยสร้าง URI ของคีย์ที่เข้ากันได้กับ Google Authenticator, แล้วส่ง URI ไปยัง openInOtpApp()

    val qrCodeUri = totpSecret.generateQrCodeUrl(
        currentUser.email ?: "default account",
        "Your App Name")
    totpSecret.openInOtpApp(qrCodeUri)
    

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

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

    // Ask the user for a verification code from the authenticator app.
    val verificationCode = // Code from user input.
    
    // Finalize the enrollment.
    val multiFactorAssertion = TotpMultiFactorGenerator
        .getAssertionForEnrollment(totpSecret, verificationCode)
    Firebase.auth.currentUser.multiFactor.enroll(multiFactorAssertion, "TOTP")
        .addOnSuccessListener {
            // Enrollment complete.
        }
    

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

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

  1. เรียกใช้เมธอด signInWith- เมธอดใดเมธอดหนึ่งเช่นเดียวกับที่คุณทำหากไม่ได้ใช้ MFA (เช่น signInWithEmailAndPassword()) หากเมธอดแสดง FirebaseAuthMultiFactorException ให้เริ่มขั้นตอน MFA ของแอป

    Firebase.auth.signInWithEmailAndPassword(email, password)
        .addOnSuccessListener { result ->
            // 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.)
    
            // ...
        }
        .addOnFailureListener { exception ->
            when (exception) {
                is FirebaseAuthMultiFactorException -> {
                    // Initiate your second factor sign-in flow. (See next step.)
                    // ...
                }
            }
        }
    
  2. ขั้นตอน MFA ของแอปควรแจ้งให้ผู้ใช้เลือกปัจจัยที่ 2 ที่ต้องการใช้ก่อน คุณดูรายการปัจจัยที่ 2 ที่รองรับได้โดยตรวจสอบพร็อพเพอร์ตี้ hints ของอินสแตนซ์ MultiFactorResolver

    val enrolledFactors = exception.resolver.hints.map { it.displayName }
    
  3. หากผู้ใช้เลือกใช้ TOTP ให้แจ้งให้ผู้ใช้พิมพ์ TOTP ที่แสดงในแอป Authenticator และใช้ TOTP นั้นเพื่อลงชื่อเข้าใช้

    when (exception.resolver.hints[selectedIndex].factorId) {
        TotpMultiFactorGenerator.FACTOR_ID -> {
            val otpFromAuthenticator = // OTP typed by the user.
            val assertion = TotpMultiFactorGenerator.getAssertionForSignIn(
                exception.resolver.hints[selectedIndex].uid,
                otpFromAuthenticator
            )
            exception.resolver.resolveSignIn(assertion)
                .addOnSuccessListener { result ->
                    // Successfully signed in!
                }
                .addOnFailureListener { resolveError ->
                    // Invalid or expired OTP.
                }
        }
        PhoneMultiFactorGenerator.FACTOR_ID -> {
            // Handle SMS second factor.
        }
    }
    

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

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

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

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

Firebase.auth.currentUser.multiFactor.unenroll(mfaEnrollmentId)
    .addOnSuccessListener {
        // Second factor unenrolled.
    }
    .addOnFailureListener { exception ->
        when (exception) {
            is FirebaseAuthInvalidUserException -> {
                // Second factor unenrolled. 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.
                val credential = EmailAuthProvider.getCredential(email, password)
                currentUser.reauthenticate(credential)
                    .addOnSuccessListener { 
                        // Success!
                    }
                    .addOnFailureListener { 
                        // Bad email address and password combination.
                    }
            }
        }
    }

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