הוסף אימות TOTP מרובה גורמים לאפליקציית iOS שלך

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

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

לפני שאתה מתחיל

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

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

  3. אם עדיין לא עשית זאת, התקן את Firebase Apple SDK .

    TOTP MFA נתמך רק בגרסה של Apple SDK v10.12.0 ומעלה, ורק ב-iOS.

אפשר TOTP MFA

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

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

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

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

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

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

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

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

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

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

רשום משתמשים ל-TOTP MFA

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

  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)
    

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

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

    let mfaKey = AuthErrorUserInfoMultiFactorResolverKey
    guard let resolver = error.userInfo[mfaKey] as? MultiFactorResolver else { return }
    let enrolledFactors = resolver.hints.map(\.displayName)
    
  3. אם המשתמש בוחר להשתמש ב-TOTP, בקש ממנו להקליד את ה-TOTP המוצג באפליקציית המאמת שלו ולהשתמש בו כדי להיכנס:

    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
    }
    

בטל את ההרשמה מ-TOTP MFA

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

אם משתמש נרשם למספר אפשרויות 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.
}

מה הלאה