איך מוסיפים אימות רב-גורמי מסוג TOTP לאפליקציה ל-Android

אם שדרגתם ל-Firebase Authentication with Identity Platform, אתם יכולים להוסיף לאפליקציה אימות רב-שלבי (MFA) באמצעות סיסמה חד-פעמית מבוססת-זמן (TOTP).

Firebase Authentication with Identity Platform מאפשר להשתמש ב-TOTP כגורם נוסף לאימות רב-שלבי (MFA). כשמפעילים את התכונה הזו, המשתמשים שמנסים להיכנס לאפליקציה רואים בקשה להזנת קוד TOTP. כדי ליצור אותו, הם צריכים להשתמש באפליקציית אימות שיכולה ליצור קודי TOTP תקינים, כמו מאמת החשבונות של Google.

לפני שמתחילים

  1. מפעילים לפחות ספק אחד שתומך באימות דו-שלבי. שימו לב שכל הספקים חוץ מהספקים הבאים תומכים באימות דו-שלבי:

    • אימות באמצעות הטלפון
    • אימות אנונימי
    • טוקנים מותאמים אישית לאימות
    • Apple Game Center
  2. מוודאים שהאפליקציה מאמתת את כתובות האימייל של המשתמשים. נדרש אימות באימייל כדי להשתמש באימות רב-שלבי. כך אפשר למנוע מגורמים זדוניים להירשם לשירות עם כתובת אימייל שלא בבעלותם, ואז לנעול את הבעלים האמיתי של כתובת האימייל על ידי הוספת אימות דו-שלבי.

  3. אם עדיין לא עשיתם זאת, אתם צריכים להתקין את Firebase Android SDK.

    אימות רב-שלבי באמצעות TOTP נתמך רק ב-Android SDK בגרסה v22.1.0 ומעלה.

הפעלת אימות רב-שלבי באמצעות TOTP

כדי להפעיל סיסמה חד-פעמית מבוססת-זמן (TOTP) כגורם אימות שני, משתמשים ב-Admin SDK או קוראים לנקודת הקצה של ה-REST API להגדרת הפרויקט.

כדי להשתמש ב-Admin SDK:

  1. אם עדיין לא עשיתם זאת, מתקינים את Firebase Admin Node.js SDK.

    אימות רב-שלבי באמצעות TOTP נתמך רק בגרסאות 11.6.0 ומעלה של Firebase Admin Node.js SDK.

  2. מריצים את הפקודה הבאה:

    import { getAuth } from 'firebase-admin/auth';
    
    getAuth().projectConfigManager().updateProjectConfig(
    {
          multiFactorConfig: {
              providerConfigs: [{
                  state: "ENABLED",
                  totpProviderConfig: {
                      adjacentIntervals: NUM_ADJ_INTERVALS
                  }
              }]
          }
    })
    

    מחליפים את מה שכתוב בשדות הבאים:

    • NUM_ADJ_INTERVALS: מספר המרווחים הסמוכים של חלונות הזמן שמהם יתקבלו קודי TOTP, מאפס עד עשר. ערך ברירת המחדל הוא 5.

      סיסמאות חד-פעמיות מבוססות-זמן פועלות כך שכאשר שני צדדים (המאמת והבודק) יוצרים סיסמאות חד-פעמיות באותו חלון זמן (בדרך כלל 30 שניות), הם יוצרים את אותה סיסמה. עם זאת, כדי להתחשב בסטייה בשעון בין הצדדים ובזמן התגובה של בני אדם, אפשר להגדיר את שירות ה-TOTP כך שיקבל גם קודי TOTP מחלונות סמוכים.

כדי להפעיל אימות רב-שלבי באמצעות TOTP באמצעות API ל-REST, מריצים את הפקודה הבאה:

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: מספר המרווחים של חלון הזמן, מאפס עד עשר. ברירת המחדל היא חמש.

    סיסמאות חד-פעמיות מבוססות-זמן פועלות כך שכאשר שני צדדים (המאמת והבודק) יוצרים סיסמאות חד-פעמיות באותו חלון זמן (בדרך כלל 30 שניות), הם יוצרים את אותה סיסמה. עם זאת, כדי להתחשב בסטייה בשעון בין הצדדים ובזמן התגובה של בני אדם, אפשר להגדיר את שירות ה-TOTP כך שיקבל גם קודי TOTP מחלונות סמוכים.

בחירת דפוס הרשמה

אתם יכולים לבחור אם האפליקציה שלכם דורשת אימות רב-שלבי, ואיך ומתי לרשום את המשתמשים. דוגמאות נפוצות:

  • רושמים את הגורם השני לאימות של המשתמש כחלק מההרשמה. כדאי להשתמש בשיטה הזו אם האפליקציה שלכם דורשת אימות רב-שלבי מכל המשתמשים.

  • הציעו אפשרות דילוג על ההרשמה לאימות דו-שלבי במהלך ההרשמה. אם אתם רוצים לעודד שימוש באימות רב-שלבי באפליקציה שלכם, אבל לא לחייב אותו, תוכלו להשתמש בגישה הזו.

  • אפשרות להוסיף אימות דו-שלבי מדף ניהול החשבון או הפרופיל של המשתמש, במקום ממסך ההרשמה. כך מצמצמים את החיכוך במהלך תהליך ההרשמה, ועדיין מאפשרים אימות רב-שלבי למשתמשים שחשובה להם האבטחה.

  • הוספה הדרגתית של שלב שני לאימות כשמשתמש רוצה לגשת לתכונות עם דרישות אבטחה מוגברות.

הרשמה של משתמשים לאימות רב-שלבי (MFA) באמצעות TOTP

אחרי שמפעילים אימות דו-שלבי באמצעות TOTP כגורם שני לאימות באפליקציה, צריך להטמיע לוגיקה בצד הלקוח כדי לרשום משתמשים לאימות דו-שלבי באמצעות 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 ולהעביר אותו אל openInOtpApp():

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

    אחרי שהמשתמש יוסיף את הסוד לאפליקציית האימות, היא תתחיל ליצור קודי TOTP.

  4. מבקשים מהמשתמש להקליד את קוד ה-TOTP שמוצג באפליקציה לאימות החשבונות, ולהשתמש בו כדי להשלים את ההרשמה לאימות רב-שלבי:

    // 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, כמו שהייתם עושים אם לא הייתם משתמשים באימות דו-שלבי. (לדוגמה, signInWithEmailAndPassword()). אם ה-method מחזיר FirebaseAuthMultiFactorException, מתחילים את תהליך האימות הרב-שלבי באפליקציה.

    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. בתהליך האימות הרב-שלבי באפליקציה, המשתמש צריך קודם לבחור את הגורם השני שבו הוא רוצה להשתמש. כדי לקבל רשימה של אמצעי אימות דו-שלבי נתמכים, אפשר לבדוק את המאפיין hints של מופע MultiFactorResolver:

    val enrolledFactors = exception.resolver.hints.map { it.displayName }
    
  3. אם המשתמש בוחר להשתמש ב-TOTP, מבקשים ממנו להקליד את ה-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

בקטע הזה מוסבר איך לטפל במשתמש שמבטל את ההרשמה שלו לאימות דו-שלבי באמצעות TOTP.

אם משתמש נרשם לכמה אפשרויות של אימות דו-שלבי, ואם הוא מבטל את ההרשמה לאפשרות שהופעלה לאחרונה, הוא מקבל הודעה ב-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.
                    }
            }
        }
    }

המאמרים הבאים