אם שדרגתם לאימות ב-Firebase באמצעות Identity Platform, תוכלו להוסיף לאפליקציה שלכם ב-Flutter אימות רב-שלבי באמצעות SMS.
אימות רב-שלבי (MFA) מגביר את האבטחה של האפליקציה. לרוב, תוקפים מצליחים לפרוץ לסיסמאות ולחשבונות ברשתות החברתיות, אבל קשה יותר להם ליירט הודעת SMS.
לפני שמתחילים
מפעילים ספק אחד לפחות שתומך באימות רב-שלבי. כל הספקים תומכים באימות דו-שלבי, למעט אימות בטלפון, אימות אנונימי ו-Apple Game Center.
מוודאים שהאפליקציה מאמתת את כתובות האימייל של המשתמשים. כדי להשתמש בשיטת אימות דו-שלבי, צריך לאמת את כתובת האימייל. כך אפשר למנוע מגורמים זדוניים להירשם לשירות באמצעות כתובת אימייל שאינה בבעלות שלהם, ולאחר מכן לנעול את הבעלים האמיתי על ידי הוספת גורם אימות שני.
Android: אם עדיין לא הגדרתם את הגיבוב SHA-256 של האפליקציה במסוף Firebase, עליכם לעשות זאת. במאמר אימות הלקוח מוסבר איך למצוא את הגיבוב SHA-256 של האפליקציה.
iOS: ב-Xcode, מפעילים את ההתראות ב-push בפרויקט ומוודאים שמפתח האימות של APNs מוגדר ב-Firebase Cloud Messaging (FCM). בנוסף, צריך להפעיל את המצבים ברקע כדי לקבל התראות מרחוק. כדי לקבל הסבר מפורט על השלב הזה, אפשר לעיין בתיעוד של אימות הטלפון ב-Firebase iOS.
אתר: מוודאים שהוספתם את הדומיין של האפליקציה במסוף Firebase, בקטע דומיינים להפניה אוטומטית מסוג OAuth.
הפעלת אימות רב-גורמי
פותחים את הדף Authentication (אימות) > Sign-in method (שיטת כניסה) במסוף Firebase.
בקטע מתקדם, מפעילים את האפשרות אימות רב-שלבי ב-SMS.
צריך גם להזין את מספרי הטלפון שבהם תבדקו את האפליקציה. למרות שלא חייבים לרשום מספרי טלפון לבדיקה, מומלץ מאוד לרשום אותם כדי למנוע ויסות נתונים (throttle) במהלך הפיתוח.
אם עדיין לא הענקת הרשאה לדומיין של האפליקציה, צריך להוסיף אותו לרשימת ההיתרים בדף Authentication > Settings במסוף Firebase.
בחירת דפוס הרישום
אתם יכולים לבחור אם האפליקציה תחייב אימות רב-שלבי, ואיך ומתי להירשם המשתמשים. דוגמאות לדפוסים נפוצים:
להירשם לגורם האימות השני של המשתמש כחלק מהרישום. כדאי להשתמש בשיטה הזו אם האפליקציה שלכם דורשת אימות רב-שלבי לכל המשתמשים.
להציע אפשרות שניתן לדלג עליה כדי לרשום שלב שני במהלך הרישום. באפליקציות שרוצות לעודד את השימוש באימות רב-שלבי, אבל לא לחייב אותו, הגישה הזו עשויה להתאים.
אפשר להוסיף גורם אימות שני מהחשבון של המשתמש או מדף ניהול הפרופיל שלו, במקום מהמסך של ההרשמה. כך תוכלו לצמצם את החיכוך בתהליך הרישום, והאימות הרב-שלבי עדיין יהיה זמין למשתמשים שרגישים לאבטחה.
מחייב להוסיף גורם נוסף באופן מצטבר כשהמשתמש רוצה לגשת לתכונות עם דרישות אבטחה מחמירות יותר.
הוספת שלב שני
כדי להירשם לגורם אימות משני חדש למשתמש:
מבצעים אימות מחדש של המשתמש.
מבקשים מהמשתמש להזין את מספר הטלפון שלו.
מקבלים סשן עם אימות רב-גורמי למשתמש:
final multiFactorSession = await user.multiFactor.getSession();
מאמתים את מספר הטלפון באמצעות סשן מרובה גורמים והקריאות החוזרות (callback):
await FirebaseAuth.instance.verifyPhoneNumber( multiFactorSession: multiFactorSession, phoneNumber: phoneNumber, verificationCompleted: (_) {}, verificationFailed: (_) {}, codeSent: (String verificationId, int? resendToken) async { // The SMS verification code has been sent to the provided phone number. // ... }, codeAutoRetrievalTimeout: (_) {}, );
אחרי שליחת קוד ה-SMS, מבקשים מהמשתמש לאמת את הקוד:
final credential = PhoneAuthProvider.credential( verificationId: verificationId, smsCode: smsCode, );
משלימים את ההרשמה:
await user.multiFactor.enroll( PhoneMultiFactorGenerator.getAssertion( credential, ), );
הקוד הבא מציג דוגמה מלאה להוספת גורם אימות שני:
final session = await user.multiFactor.getSession();
final auth = FirebaseAuth.instance;
await auth.verifyPhoneNumber(
multiFactorSession: session,
phoneNumber: phoneController.text,
verificationCompleted: (_) {},
verificationFailed: (_) {},
codeSent: (String verificationId, int? resendToken) async {
// See `firebase_auth` example app for a method of retrieving user's sms code:
// https://github.com/firebase/flutterfire/blob/master/packages/firebase_auth/firebase_auth/example/lib/auth.dart#L591
final smsCode = await getSmsCodeFromUser(context);
if (smsCode != null) {
// Create a PhoneAuthCredential with the code
final credential = PhoneAuthProvider.credential(
verificationId: verificationId,
smsCode: smsCode,
);
try {
await user.multiFactor.enroll(
PhoneMultiFactorGenerator.getAssertion(
credential,
),
);
} on FirebaseAuthException catch (e) {
print(e.message);
}
}
},
codeAutoRetrievalTimeout: (_) {},
);
כל הכבוד! רשמתם בהצלחה גורם אימות שני למשתמש.
כניסה של משתמשים באמצעות גורם אימות שני
כדי להיכנס למשתמש באמצעות אימות דו-שלבי באמצעות SMS:
נכנסים עם המשתמש באמצעות הגורם הראשון, ואז תופסים את היוצא מן הכלל
FirebaseAuthMultiFactorException
. השגיאה הזו מכילה פותר (resolver) שבעזרתו אפשר לקבל את הגורמים הנוספים לאימות שהמשתמש רשם. הוא מכיל גם סשן בסיסי שמוכיח שהמשתמש אומת בהצלחה באמצעות הגורם הראשון.לדוגמה, אם הגורם הראשון שגרם למשתמש הוא כתובת אימייל וסיסמה:
try { await _auth.signInWithEmailAndPassword( email: emailController.text, password: passwordController.text, ); // User is not enrolled with a second factor and is successfully // signed in. // ... } on FirebaseAuthMultiFactorException catch (e) { // The user is a multi-factor user. Second factor challenge is required final resolver = e.resolver // ... }
אם למשתמש יש כמה גורמים משניים רשומים, צריך לשאול אותו באיזה מהם להשתמש:
final session = e.resolver.session; final hint = e.resolver.hints[selectedHint];
שולחים הודעה לאימות לטלפון של המשתמש עם ההצעה והסשן של אימות הרבה-גורמים:
await FirebaseAuth.instance.verifyPhoneNumber( multiFactorSession: session, multiFactorInfo: hint, verificationCompleted: (_) {}, verificationFailed: (_) {}, codeSent: (String verificationId, int? resendToken) async { // ... }, codeAutoRetrievalTimeout: (_) {}, );
כדי להשלים את האימות המשני, צריך להפעיל את
resolver.resolveSignIn()
:final smsCode = await getSmsCodeFromUser(context); if (smsCode != null) { // Create a PhoneAuthCredential with the code final credential = PhoneAuthProvider.credential( verificationId: verificationId, smsCode: smsCode, ); try { await e.resolver.resolveSignIn( PhoneMultiFactorGenerator.getAssertion(credential) ); } on FirebaseAuthException catch (e) { print(e.message); } }
הקוד הבא מציג דוגמה מלאה לכניסה של משתמש עם אימות רב-גורמי:
try {
await _auth.signInWithEmailAndPassword(
email: emailController.text,
password: passwordController.text,
);
} on FirebaseAuthMultiFactorException catch (e) {
setState(() {
error = '${e.message}';
});
final firstHint = e.resolver.hints.first;
if (firstHint is! PhoneMultiFactorInfo) {
return;
}
await FirebaseAuth.instance.verifyPhoneNumber(
multiFactorSession: e.resolver.session,
multiFactorInfo: firstHint,
verificationCompleted: (_) {},
verificationFailed: (_) {},
codeSent: (String verificationId, int? resendToken) async {
// See `firebase_auth` example app for a method of retrieving user's sms code:
// https://github.com/firebase/flutterfire/blob/master/packages/firebase_auth/firebase_auth/example/lib/auth.dart#L591
final smsCode = await getSmsCodeFromUser(context);
if (smsCode != null) {
// Create a PhoneAuthCredential with the code
final credential = PhoneAuthProvider.credential(
verificationId: verificationId,
smsCode: smsCode,
);
try {
await e.resolver.resolveSignIn(
PhoneMultiFactorGenerator.getAssertion(
credential,
),
);
} on FirebaseAuthException catch (e) {
print(e.message);
}
}
},
codeAutoRetrievalTimeout: (_) {},
);
} catch (e) {
...
}
כל הכבוד! התחברתם בהצלחה למשתמש באמצעות אימות רב-גורמי.
המאמרים הבאים
- ניהול משתמשים עם אימות רב-שלבי באופן פרוגרמטי באמצעות Admin SDK.