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

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

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

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

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

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

ลงทะเบียนผู้ใช้ใน 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. แสดงรหัสลับต่อผู้ใช้และแจ้งให้ผู้ใช้ป้อนรหัสลับลงในแอป Authenticator

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

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

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

    หลังจากผู้ใช้เพิ่มข้อมูลลับลงในแอป Authenticator แล้ว แอปจะเริ่มสร้าง 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.
                    }
            }
        }
    }

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