אימות באמצעות Firebase באמצעות קישורי אימייל

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

יש הרבה יתרונות לכניסה באמצעות אימייל:

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

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

  1. אם עדיין לא עשיתם את זה, אתם צריכים לפעול לפי השלבים במדריך תחילת העבודה.

  2. מפעילים את הכניסה באמצעות קישור באימייל בפרויקט Firebase.

    כדי לאפשר למשתמשים להיכנס באמצעות קישור באימייל, קודם צריך להפעיל את ספק האימייל ואת שיטת הכניסה באמצעות קישור באימייל בפרויקט Firebase:

    1. במסוף Firebase, פותחים את הקטע אימות.
    2. בכרטיסייה Sign in method (שיטת כניסה), מפעילים את ספק Email/Password (אימייל/סיסמה). שימו לב: כדי להשתמש בכניסה באמצעות קישור באימייל, צריך להפעיל את הכניסה באמצעות אימייל או סיסמה.
    3. באותו קטע, מפעילים את שיטת הכניסה קישור באימייל (כניסה ללא סיסמה).
    4. לוחצים על שמירה.

כדי להתחיל את תהליך האימות, מציגים ממשק שמבקש מהמשתמש לספק את כתובת האימייל שלו, ואז קוראים ל-sendSignInLinkToEmail() כדי לבקש מ-Firebase לשלוח את קישור האימות לכתובת האימייל של המשתמש.

  1. יוצרים את האובייקט ActionCodeSettings, שמספק ל-Firebase הוראות לגבי אופן יצירת הקישור לאימייל. מגדירים את השדות הבאים:

    • url: קישור העומק להטמעה וכל מצב נוסף שרוצים להעביר. הדומיין של הקישור צריך להופיע ברשימת הדומיינים המורשים במסוף Firebase. כדי לראות את הרשימה, עוברים לכרטיסייה Settings (הגדרות) (Authentication (אימות) -> Settings (הגדרות) -> Authorized Domains (דומיינים מורשים)). הקישור יפנה את המשתמש לכתובת ה-URL הזו אם האפליקציה לא מותקנת במכשיר שלו ולא ניתן להתקין אותה.

    • androidPackageName ו-IOSBundleId: האפליקציות שבהן יש להשתמש כשפותחים את קישור הכניסה במכשיר Android או iOS. מידע נוסף על הגדרת קישורי עומק דינמיים ב-Firebase כדי לפתוח קישורים לפעולות באימייל דרך אפליקציות לנייד

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

    • dynamicLinkDomain: (הוצא משימוש, צריך להשתמש ב-linkDomain) אם מוגדרים כמה דומיינים מותאמים אישית של קישורים דינמיים לפרויקט, צריך לציין באיזה מהם להשתמש כשפותחים את הקישור באמצעות אפליקציה ספציפית לנייד (לדוגמה, example.page.link). אחרת, הדומיין הראשון נבחר באופן אוטומטי.

    • linkDomain: דומיין Firebase Hosting מותאם אישית אופציונלי לשימוש כשפותחים את הקישור באמצעות אפליקציה ספציפית לנייד. הדומיין צריך להיות מוגדר ב-Firebase Hosting ולהיות בבעלות הפרויקט. אי אפשר להשתמש כאן בדומיין אירוח שמוגדר כברירת מחדל (web.app או firebaseapp.com). ההגדרה הזו מחליפה את ההגדרה dynamicLinkDomain שיצאה משימוש.

    var acs = ActionCodeSettings(
        // URL you want to redirect back to. The domain (www.example.com) for this
        // URL must be whitelisted in the Firebase Console.
        url: 'https://www.example.com/finishSignUp?cartId=1234',
        // This must be true
        handleCodeInApp: true,
        iOSBundleId: 'com.example.ios',
        androidPackageName: 'com.example.android',
        // installIfNotAvailable
        androidInstallApp: true,
        // minimumVersion
        androidMinimumVersion: '12');
    
  2. בקשו מהמשתמש את כתובת האימייל שלו.

  3. שולחים את קישור האימות לאימייל של המשתמש ושומרים את כתובת האימייל של המשתמש למקרה שהמשתמש ישלים את הכניסה באמצעות האימייל באותו מכשיר.

    var emailAuth = 'someemail@domain.com';
    FirebaseAuth.instance.sendSignInLinkToEmail(
            email: emailAuth, actionCodeSettings: acs)
        .catchError((onError) => print('Error sending email verification $onError'))
        .then((value) => print('Successfully sent email verification'));
    });
    

חששות לגבי אבטחה

כדי למנוע שימוש בקישור להתחברות לצורך התחברות כמשתמש לא רצוי או במכשיר לא רצוי, Firebase Auth דורש לספק את כתובת האימייל של המשתמש כשמשלימים את תהליך ההתחברות. כדי שהכניסה תצליח, כתובת האימייל הזו צריכה להיות זהה לכתובת שאליה נשלח במקור קישור הכניסה.

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

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

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

השלמת הכניסה

התמיכה בקישורים דינמיים ב-Firebase הופסקה. עכשיו משתמשים ב-Firebase Hosting כדי לשלוח קישור לכניסה. פועלים לפי המדריכים להגדרות ספציפיות לפלטפורמה:

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

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

    // Confirm the link is a sign-in with email link.
    if (FirebaseAuth.instance.isSignInWithEmailLink(emailLink)) {
      try {
        // The client SDK will parse the code from the link for you.
        final userCredential = await FirebaseAuth.instance
            .signInWithEmailLink(email: emailAuth, emailLink: emailLink);
    
        // You can access the new user via userCredential.user.
        final emailAddress = userCredential.user?.email;
    
        print('Successfully signed in with email link!');
      } catch (error) {
        print('Error signing in with email link.');
      }
    }
    

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

ההבדל יהיה במחצית השנייה של הפעולה:

final authCredential = EmailAuthProvider
    .credentialWithLink(email: emailAuth, emailLink: emailLink.toString());
try {
    await FirebaseAuth.instance.currentUser
        ?.linkWithCredential(authCredential);
} catch (error) {
    print("Error linking emailLink credential.");
}

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

final authCredential = EmailAuthProvider
    .credentialWithLink(email: emailAuth, emailLink: emailLink.toString());
try {
    await FirebaseAuth.instance.currentUser
        ?.reauthenticateWithCredential(authCredential);
} catch (error) {
    print("Error reauthenticating credential.");
}

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

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

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

פרטים נוספים זמינים במאמר בנושא הגנה מפני ספירת כתובות אימייל.

השלבים הבאים

אחרי שמשתמש יוצר חשבון חדש, החשבון הזה נשמר כחלק מפרויקט Firebase שלכם, ואפשר להשתמש בו כדי לזהות משתמש בכל אפליקציה בפרויקט, בלי קשר לשיטת הכניסה שבה המשתמש השתמש.

באפליקציות, אפשר לקבל את פרטי הפרופיל הבסיסיים של המשתמש מאובייקט User. איך מנהלים משתמשים

בכללי האבטחה של Firebase Realtime Database ו-Cloud Storage, אפשר לקבל את מזהה המשתמש הייחודי של המשתמש המחובר מהמשתנה auth ולהשתמש בו כדי לשלוט בנתונים שהמשתמש יכול לגשת אליהם.

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

כדי להוציא משתמש מהחשבון, קוראים ל-signOut():

await FirebaseAuth.instance.signOut();