אם שדרגתם ל-Firebase Authentication with Identity Platform, אתם יכולים להוסיף לאפליקציה אימות רב-שלבי (MFA) באמצעות סיסמה חד-פעמית מבוססת-זמן (TOTP).
Firebase Authentication with Identity Platform מאפשר להשתמש ב-TOTP כגורם נוסף לאימות רב-שלבי (MFA). כשמפעילים את התכונה הזו, המשתמשים שמנסים להיכנס לאפליקציה רואים בקשה להזנת קוד TOTP. כדי ליצור אותו, הם צריכים להשתמש באפליקציית אימות שיכולה ליצור קודי TOTP תקינים, כמו מאמת החשבונות של Google.
לפני שמתחילים
מפעילים לפחות ספק אחד שתומך באימות דו-שלבי. שימו לב שכל הספקים חוץ מהספקים הבאים תומכים באימות דו-שלבי:
- אימות באמצעות הטלפון
- אימות אנונימי
- טוקנים מותאמים אישית לאימות
- Apple Game Center
מוודאים שהאפליקציה מאמתת את כתובות האימייל של המשתמשים. נדרש אימות באימייל כדי להשתמש באימות רב-שלבי. כך אפשר למנוע מגורמים זדוניים להירשם לשירות עם כתובת אימייל שלא בבעלותם, ואז לנעול את הגישה לבעלים האמיתי של כתובת האימייל על ידי הוספת אמצעי אימות נוסף.
אם עוד לא עשיתם זאת, אתם צריכים להתקין את Firebase JavaScript SDK.
אימות רב-שלבי באמצעות TOTP נתמך רק ב-Web SDK מודולרי, בגרסאות v9.19.1 ומעלה.
הפעלת אימות רב-שלבי באמצעות TOTP
כדי להפעיל סיסמה חד-פעמית מבוססת-זמן (TOTP) כגורם אימות שני, משתמשים ב-Admin SDK או קוראים לנקודת הקצה של ה-REST API להגדרת הפרויקט.
כדי להשתמש ב-Admin SDK:
אם עדיין לא עשיתם זאת, מתקינים את Firebase Admin Node.js SDK.
אימות רב-שלבי באמצעות TOTP נתמך רק בגרסאות 11.6.0 ומעלה של Firebase Admin Node.js SDK.
מריצים את הפקודה הבאה:
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:
מייבאים את הפונקציות והמחלקות הנדרשות של MFA:
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. כדי ליצור קוד 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 שמוצג באפליקציה לאימות החשבונות, ולהשתמש בו כדי להשלים את ההרשמה לאימות רב-שלבי:
// 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 MFA, משתמשים בקוד הבא:
מייבאים את הפונקציות והמחלקות הנדרשות של MFA:
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
בקטע הזה מוסבר איך לטפל במשתמש שמבטל את ההרשמה שלו לאימות דו-שלבי באמצעות 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.