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

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

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

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

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

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

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

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

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

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

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

    • url: קישור העומק להטמעה וכל מצב נוסף שרוצים להעביר. הדומיין של הקישור צריך להופיע ברשימת הדומיינים המורשים במסוף Firebase. אפשר למצוא את הרשימה בכרטיסייה 'הגדרות' (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 מחייב לספק את כתובת האימייל של המשתמש במהלך תהליך הכניסה. כדי שהכניסה תתבצע, כתובת האימייל הזו צריכה להתאים לכתובת שאליה נשלח הקישור לכניסה במקור.

כדי לייעל את התהליך הזה למשתמשים שפותחים את הקישור לכניסה באותו מכשיר שבו הם מבקשים את הקישור, אפשר לשמור את כתובת האימייל שלהם באופן מקומי – למשל באמצעות 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();