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

หากอัปเกรดเป็น 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 Android SDK

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

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

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

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

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

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

  4. แจ้งให้ผู้ใช้พิมพ์ TOTP ที่แสดงโดยแอป Authenticator และ ใช้เพื่อลงทะเบียน 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.
        }
    

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

หากต้องการลงชื่อเข้าใช้ผู้ใช้ด้วย 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 แล้วใช้เพื่อลงชื่อเข้าใช้

    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.
        }
    }
    

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

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

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

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