אם שדרגתם ל-Firebase Authentication with Identity Platform, תוכלו להוסיף לאפליקציה אימות רב-שלבי (MFA) באמצעות סיסמה חד-פעמית מבוססת-זמן (TOTP).
Firebase Authentication with Identity Platform מאפשר להשתמש ב-TOTP כגורם נוסף לאימות רב-שלבי. כשמפעילים את התכונה הזו, משתמשים שמנסים להיכנס לאפליקציה רואים בקשה ל-TOTP. כדי ליצור אותו, הם צריכים להשתמש באפליקציית אימות שיכולה ליצור קודי TOTP תקפים, כמו מאמת החשבונות של Google.
לפני שמתחילים
מפעילים ספק אחד לפחות שתומך ב-MFA. חשוב לזכור שכל הספקים למעט הספקים הבאים תומכים באימות דו-שלבי:
- אימות הטלפון
- אימות אנונימי
- טוקני אימות בהתאמה אישית
- Apple Game Center
חשוב לוודא שהאפליקציה מאמתת את כתובות האימייל של המשתמשים. כדי להשתמש בשיטת אימות דו-שלבי, צריך לאמת את כתובת האימייל. כך אפשר למנוע מגורמים זדוניים להירשם לשירות באמצעות כתובת אימייל שאינה בבעלותם, ולאחר מכן לנעול את הבעלים האמיתי של כתובת האימייל על ידי הוספת גורם שני.
אם עדיין לא עשיתם זאת, מתקינים את Firebase JavaScript SDK.
יש תמיכה בשיטת האימות הדו-שלבי באמצעות קוד TOTP רק ב-Web SDK המודולרי, בגרסאות 9.19.1 ואילך.
הפעלת אימות דו-שלבי באמצעות TOTP
כדי להפעיל את TOTP כגורם שני, משתמשים ב-Admin SDK או קוראים לנקודת הקצה של ה-REST של הגדרות הפרויקט.
כדי להשתמש ב-Admin SDK:
אם עדיין לא עשיתם זאת, מתקינים את ה-SDK של Firebase Admin עבור Node.js.
יש תמיכה בשיטת האימות הדו-שלבי באמצעות TOTP רק ב-SDK של Firebase Admin עבור Node.js בגרסה 11.6.0 ואילך.
מריצים את הפקודה הבאה:
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 מבטיח שכאשר שני צדדים (המוכיח והמאמת) יוצרים אסימוני OTP באותו חלון זמן (בדרך כלל 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
: מספר הפסקות בחלון הזמן, מ-0 עד 10. ערך ברירת המחדל הוא 5.המנגנון של TOTP מבטיח שכאשר שני צדדים (המוכיח והמאמת) יוצרים אסימוני OTP באותו חלון זמן (בדרך כלל 30 שניות), הם יוצרים את אותה סיסמה. עם זאת, כדי להתאים את השעון בין הצדדים לזמן התגובה האנושי, אפשר להגדיר את שירות ה-TOTP כך שיקבל גם קודי TOTP מחלונות סמוכים.
בחירת דפוס ההרשמה
אתם יכולים לבחור אם האפליקציה תחייב אימות רב-שלבי, ואיך ומתי להירשם את המשתמשים. דוגמאות לדפוסים נפוצים:
להירשם לגורם האימות השני של המשתמש כחלק מהרישום. כדאי להשתמש בשיטה הזו אם האפליקציה שלכם דורשת אימות רב-שלבי לכל המשתמשים.
כדאי להציע אפשרות לדלג על ההרשמה של גורם אימות שני במהלך ההרשמה. אם אתם רוצים לעודד את המשתמשים להשתמש באימות רב-שלבי באפליקציה, אבל לא לחייב אותם לעשות זאת, תוכלו להשתמש בגישה הזו.
אפשר להוסיף גורם אימות שני מהחשבון של המשתמש או מהדף לניהול הפרופיל, במקום במסך ההרשמה. כך אפשר לצמצם את החיכוך בתהליך ההרשמה, ועדיין להציע אימות רב-שלבי למשתמשים שמתעניינים באבטחה.
מחייב להוסיף גורם נוסף באופן מצטבר כשהמשתמש רוצה לגשת לתכונות עם דרישות אבטחה מחמירות יותר.
הרשמה של משתמשים לאימות דו-שלבי באמצעות TOTP
אחרי שמפעילים את אימות הגורם השני מסוג TOTP באפליקציה, מטמיעים לוגיקה בצד הלקוח כדי לרשום משתמשים לאימות הגורם השני מסוג TOTP:
מייבאים את הכיתות והפונקציות הנדרשות של אימות דו-שלבי:
import { multiFactor, TotpMultiFactorGenerator, TotpSecret, getAuth, } from "firebase/auth";
מבצעים אימות מחדש של המשתמש.
יוצרים סוד TOTP למשתמש המאומת:
// Generate a TOTP secret. const multiFactorSession = await multiFactor(currentUser).getSession(); const totpSecret = await TotpMultiFactorGenerator.generateSecret( multiFactorSession );
מציגים את הסוד למשתמש ומבקשים ממנו להזין אותו באפליקציית האימות שלו.
באפליקציות אימות רבות, המשתמשים יכולים להוסיף במהירות סודות TOTP חדשים על ידי סריקת קוד QR שמייצג URI של מפתח תואם ל-Google Authenticator. כדי ליצור קוד QR למטרה הזו, יוצרים את ה-URI באמצעות
generateQrCodeUrl()
ואז מקודדים אותו באמצעות ספריית קוד ה-QR שבוחרים. לדוגמה:const totpUri = totpSecret.generateQrCodeUrl( currentUser.email, "Your App's Name" ); await QRExampleLib.toCanvas(totpUri, qrElement);
לא משנה אם אתם מציגים קוד QR, תמיד צריך להציג את המפתח הסודי כדי לתמוך באפליקציות אימות שלא יכולות לקרוא קודי QR:
// Also display this key: const secret = totpSecret.secretKey;
אחרי שהמשתמש מוסיף את הסוד לאפליקציית האימות, היא מתחילה ליצור אסימוני TOTP.
מבקשים מהמשתמש להקליד את קוד ה-TOTP שמוצג באפליקציית האימות שלו, ולהשתמש בו כדי להשלים את ההרשמה ל-MFA:
// Ask the user for a verification code from the authenticator app. const verificationCode = // Code from user input. // Finalize the enrollment. const multiFactorAssertion = TotpMultiFactorGenerator.assertionForEnrollment( totpSecret, verificationCode ); await multiFactor(currentUser).enroll(multiFactorAssertion, mfaDisplayName);
כניסה של משתמשים באמצעות גורם אימות שני
כדי להתחבר משתמשים באמצעות אימות דו-שלבי מסוג TOTP, משתמשים בקוד הבא:
מייבאים את הכיתות והפונקציות הנדרשות של אימות דו-שלבי:
import { getAuth, getMultiFactorResolver, TotpMultiFactorGenerator, } from "firebase/auth";
קוראים לאחת מהשיטות עם
signInWith
כמו שאתם עושים אם אתם לא משתמשים בשיטת אימות דו-שלבי. (לדוגמה,signInWithEmailAndPassword()
). אם השיטה מחזירה את השגיאהauth/multi-factor-auth-required
, מתחילים את תהליך האימות הדו-שלבי של האפליקציה.try { const userCredential = await signInWithEmailAndPassword( getAuth(), email, 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 (error) { switch (error.code) { case "auth/multi-factor-auth-required": // Initiate your second factor sign-in flow. (See next step.) // ... break; case ...: // Handle other errors, such as wrong passwords. break; } }
בתהליך האימות הדו-שלבי של האפליקציה, המשתמש צריך לבחור קודם את הגורם השני שבו הוא רוצה להשתמש. כדי לקבל רשימה של גורמים שניים נתמכים, אפשר לבדוק את המאפיין
hints
של מכונהMultiFactorResolver
:const mfaResolver = getMultiFactorResolver(getAuth(), error); const enrolledFactors = mfaResolver.hints.map(info => info.displayName);
אם המשתמש בוחר להשתמש ב-TOTP, מבקשים ממנו להקליד את ה-TOTP שמוצג באפליקציית האימות שלו ולהשתמש בו כדי להיכנס:
switch (mfaResolver.hints[selectedIndex].factorId) { case TotpMultiFactorGenerator.FACTOR_ID: const otpFromAuthenticator = // OTP typed by the user. const multiFactorAssertion = TotpMultiFactorGenerator.assertionForSignIn( mfaResolver.hints[selectedIndex].uid, otpFromAuthenticator ); try { const userCredential = await mfaResolver.resolveSignIn( multiFactorAssertion ); // Successfully signed in! } catch (error) { // Invalid or expired OTP. } break; case PhoneMultiFactorGenerator.FACTOR_ID: // Handle SMS second factor. break; default: // Unsupported second factor? break; }
ביטול ההרשמה לאימות דו-שלבי באמצעות TOTP
בקטע הזה מוסבר איך מטפלים במצב שבו משתמש מבטל את ההרשמה ל-MFA באמצעות TOTP.
אם משתמש נרשם לכמה אפשרויות של אימות דו-שלבי, והוא מבטל את ההרשמה מהאפשרות שהופעל לאחרונה, הוא יקבל הודעת auth/user-token-expired
והוא יוסר מהחשבון. המשתמש צריך להיכנס שוב ולאמת את פרטי הכניסה הקיימים שלו – למשל, כתובת אימייל וסיסמה.
כדי לבטל את ההרשמה של המשתמש, לטפל בשגיאה ולהפעיל אימות מחדש, משתמשים בקוד הבא:
import {
EmailAuthProvider,
TotpMultiFactorGenerator,
getAuth,
multiFactor,
reauthenticateWithCredential,
} from "firebase/auth";
try {
// Unenroll from TOTP MFA.
await multiFactor(currentUser).unenroll(mfaEnrollmentId);
} catch (error) {
if (error.code === 'auth/user-token-expired') {
// 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.
const credential = EmailAuthProvider.credential(email, password);
await reauthenticateWithCredential(
currentUser,
credential
);
}
}
המאמרים הבאים
- ניהול משתמשים עם אימות רב-גורמי באופן פרוגרמטי באמצעות Admin SDK.