אתם יכולים להשתמש באימות ב-Firebase כדי לאפשר למשתמש להיכנס לחשבון על ידי שליחת אימייל עם קישור, שאפשר ללחוץ עליו כדי להיכנס לחשבון. במהלך התהליך, כתובת האימייל של המשתמש מאומתת גם היא.
יש הרבה יתרונות לכניסה באמצעות אימייל:
- הרשמה וכניסה פשוטות ומהירות.
- הסיכון לשימוש חוזר בסיסמאות באפליקציות שונות נמוך יותר, מה שיכול לפגוע באבטחה של סיסמאות שנבחרו בקפידה.
- היכולת לאמת משתמש וגם לוודא שהוא הבעלים הלגיטימי של כתובת אימייל.
- משתמשים צריכים רק חשבון אימייל נגיש כדי להיכנס. לא נדרשת בעלות על מספר טלפון או על חשבון במדיה החברתית.
- משתמש יכול להיכנס לחשבון בצורה מאובטחת בלי לספק (או לזכור) סיסמה, מה שיכול להיות מסורבל במכשיר נייד.
- משתמש קיים שנכנס בעבר באמצעות מזהה אימייל (סיסמה או איחוד) יכול לשדרג את הכניסה שלו כך שתתבצע רק באמצעות האימייל. לדוגמה, משתמש ששכח את הסיסמה שלו עדיין יכול להיכנס לחשבון בלי לאפס את הסיסמה.
לפני שמתחילים
אם עדיין לא עשיתם זאת, מעתיקים את קטע הקוד לאתחול ממסוף Firebase לפרויקט, כמו שמתואר במאמר הוספת Firebase לפרויקט JavaScript.
הפעלת התחברות באמצעות קישור באימייל בפרויקט Firebase
כדי לאפשר למשתמשים להיכנס באמצעות קישור באימייל, קודם צריך להפעיל את ספק האימייל ואת שיטת הכניסה באמצעות קישור באימייל בפרויקט Firebase:
במסוף Firebase, עוברים אל Security (אבטחה) > Authentication (אימות).
בכרטיסייה שיטת כניסה, מפעילים את שיטת הכניסה אימייל/סיסמה. שימו לב: כדי להשתמש בכניסה באמצעות קישור באימייל, צריך להפעיל את הכניסה באמצעות אימייל או סיסמה.
באותו קטע, מפעילים את ספק הכניסה Email link (passwordless sign-in) (קישור באימייל (כניסה ללא סיסמה)).
לוחצים על שמירה.
שליחת קישור אימות לכתובת האימייל של המשתמש
כדי להתחיל את תהליך האימות, מציגים למשתמש ממשק שבו הוא מתבקש לספק את כתובת האימייל שלו, ואז קוראים ל-sendSignInLinkToEmail כדי לבקש מ-Firebase לשלוח את קישור האימות לכתובת האימייל של המשתמש.
יוצרים את האובייקט
ActionCodeSettings, שמספק ל-Firebase הוראות ליצירת הקישור לאימייל. מגדירים את השדות הבאים:
url: קישור העומק להטמעה וכל מצב נוסף שרוצים להעביר. אם עדיין לא עשיתם את זה, מוסיפים את הדומיין לרשימת הדומיינים המורשים:במסוף Firebase, עוברים אל Security (אבטחה) > Authentication (אימות) > הכרטיסייה Settings (הגדרות).
בקטע דומיינים מורשים, לוחצים על הוספת דומיין ומוסיפים את הדומיין.
-
androidו-ios: עוזרים ל-Firebase Authentication לקבוע אם ליצור קישור לאתר בלבד או קישור לנייד שנפתח במכשיר Android או Apple. -
handleCodeInApp: מוגדר ל-true. פעולת הכניסה תמיד צריכה להתבצע באפליקציה, בניגוד לפעולות אחרות באימייל מחוץ לפס (איפוס סיסמה ואימותים באימייל). הסיבה לכך היא שבסוף התהליך, המשתמש אמור להיות מחובר לחשבון ומצב האימות שלו אמור להישמר באפליקציה. -
linkDomain: כשמוגדרים דומיינים מותאמים אישית של קישורים ל-Hosting בפרויקט, צריך לציין באיזה מהם להשתמש כשפותחים את הקישור באפליקציה ספציפית לנייד. אחרת, הדומיין שמוגדר כברירת מחדל נבחר באופן אוטומטי (לדוגמה, ).PROJECT_ID.firebaseapp.com
dynamicLinkDomain: הוצא משימוש. אל תציינו את הפרמטר הזה.Web
const actionCodeSettings = { // URL you want to redirect back to. The domain (www.example.com) for this // URL must be in the authorized domains list in the Firebase Console. url: 'https://www.example.com/finishSignUp?cartId=1234', // This must be true. handleCodeInApp: true, iOS: { bundleId: 'com.example.ios' }, android: { packageName: 'com.example.android', installApp: true, minimumVersion: '12' }, // The domain must be configured in Firebase Hosting and owned by the project. linkDomain: 'custom-domain.com' };
Web
var actionCodeSettings = { // URL you want to redirect back to. The domain (www.example.com) for this // URL must be in the authorized domains list in the Firebase Console. url: 'https://www.example.com/finishSignUp?cartId=1234', // This must be true. handleCodeInApp: true, iOS: { bundleId: 'com.example.ios' }, android: { packageName: 'com.example.android', installApp: true, minimumVersion: '12' }, dynamicLinkDomain: 'example.page.link' };
מידע נוסף על
ActionCodeSettingsאפשר למצוא בקטע העברת מצב בפעולות באימייל.בקשת כתובת האימייל מהמשתמש.
שולחים את קישור האימות לאימייל של המשתמש ושומרים את כתובת האימייל של המשתמש למקרה שהמשתמש ישלים את הכניסה באמצעות האימייל באותו מכשיר.
Web
import { getAuth, sendSignInLinkToEmail } from "firebase/auth"; const auth = getAuth(); sendSignInLinkToEmail(auth, email, actionCodeSettings) .then(() => { // The link was successfully sent. Inform the user. // Save the email locally so you don't need to ask the user for it again // if they open the link on the same device. window.localStorage.setItem('emailForSignIn', email); // ... }) .catch((error) => { const errorCode = error.code; const errorMessage = error.message; // ... });
Web
firebase.auth().sendSignInLinkToEmail(email, actionCodeSettings) .then(() => { // The link was successfully sent. Inform the user. // Save the email locally so you don't need to ask the user for it again // if they open the link on the same device. window.localStorage.setItem('emailForSignIn', email); // ... }) .catch((error) => { var errorCode = error.code; var errorMessage = error.message; // ... });
השלמת הכניסה באמצעות הקישור באימייל
בעיות אבטחה
כדי למנוע שימוש בקישור לכניסה לצורך כניסה כמשתמש לא רצוי או במכשיר לא רצוי, Firebase Auth דורש לספק את כתובת האימייל של המשתמש כשמשלימים את תהליך הכניסה. כדי שהכניסה תצליח, כתובת האימייל הזו צריכה להיות זהה לכתובת שאליה נשלח במקור הקישור לכניסה.
כדי לייעל את התהליך הזה למשתמשים שפותחים את קישור הכניסה באותו מכשיר שבו הם מבקשים את הקישור, אפשר לאחסן את כתובת האימייל שלהם באופן מקומי – למשל באמצעות localStorage או קובצי Cookie – כששולחים את אימייל הכניסה. אחר כך, משתמשים בכתובת הזו כדי להשלים את התהליך. אל תעבירו את כתובת האימייל של המשתמש בפרמטרים של כתובת ה-URL להפניה או תשתמשו בה מחדש, כי פעולה כזו עלולה לאפשר הזרקת סשנים.
אחרי שהמשתמשים יסיימו את הכניסה, כל מנגנון כניסה קודם שלא אומת יוסר מהמשתמש, וכל הסשנים הקיימים יבוטלו. לדוגמה, אם מישהו יצר בעבר חשבון לא מאומת עם אותה כתובת אימייל וסיסמה, הסיסמה של המשתמש תוסר כדי למנוע מהמתחזה שטען לבעלות ויצר את החשבון הלא מאומת להיכנס שוב עם כתובת האימייל והסיסמה הלא מאומתות.
בנוסף, חשוב לוודא שמשתמשים בכתובת URL עם HTTPS בסביבת הייצור כדי למנוע מצב שבו שרתים מתווכים עלולים ליירט את הקישור.
השלמת הכניסה בדף אינטרנט
הפורמט של קישור העומק של קישור האימייל זהה לפורמט שמשמש לפעולות באימייל מחוץ לפס (אימות אימייל, איפוס סיסמה וביטול שינוי אימייל).
ה-API של isSignInWithEmailLink מאפשר לבדוק בקלות אם קישור הוא קישור לכניסה באמצעות אימייל.
כדי להשלים את הכניסה בדף הנחיתה, צריך להפעיל את הפונקציה signInWithEmailLink עם כתובת האימייל של המשתמש והקישור בפועל לאימייל שמכיל את הקוד החד-פעמי.
Web
import { getAuth, isSignInWithEmailLink, signInWithEmailLink } from "firebase/auth"; // Confirm the link is a sign-in with email link. const auth = getAuth(); if (isSignInWithEmailLink(auth, window.location.href)) { // Additional state parameters can also be passed via URL. // This can be used to continue the user's intended action before triggering // the sign-in operation. // Get the email if available. This should be available if the user completes // the flow on the same device where they started it. let email = window.localStorage.getItem('emailForSignIn'); if (!email) { // User opened the link on a different device. To prevent session fixation // attacks, ask the user to provide the associated email again. For example: email = window.prompt('Please provide your email for confirmation'); } // The client SDK will parse the code from the link for you. signInWithEmailLink(auth, email, window.location.href) .then((result) => { // Clear email from storage. window.localStorage.removeItem('emailForSignIn'); // You can access the new user by importing getAdditionalUserInfo // and calling it with result: // getAdditionalUserInfo(result) // You can access the user's profile via: // getAdditionalUserInfo(result)?.profile // You can check if the user is new or existing: // getAdditionalUserInfo(result)?.isNewUser }) .catch((error) => { // Some error occurred, you can inspect the code: error.code // Common errors could be invalid email and invalid or expired OTPs. }); }
Web
// Confirm the link is a sign-in with email link. if (firebase.auth().isSignInWithEmailLink(window.location.href)) { // Additional state parameters can also be passed via URL. // This can be used to continue the user's intended action before triggering // the sign-in operation. // Get the email if available. This should be available if the user completes // the flow on the same device where they started it. var email = window.localStorage.getItem('emailForSignIn'); if (!email) { // User opened the link on a different device. To prevent session fixation // attacks, ask the user to provide the associated email again. For example: email = window.prompt('Please provide your email for confirmation'); } // The client SDK will parse the code from the link for you. firebase.auth().signInWithEmailLink(email, window.location.href) .then((result) => { // Clear email from storage. window.localStorage.removeItem('emailForSignIn'); // You can access the new user via result.user // Additional user info profile not available via: // result.additionalUserInfo.profile == null // You can check if the user is new or existing: // result.additionalUserInfo.isNewUser }) .catch((error) => { // Some error occurred, you can inspect the code: error.code // Common errors could be invalid email and invalid or expired OTPs. }); }
השלמת הכניסה באפליקציה לנייד
Firebase Authentication משתמש ב-Firebase Hosting כדי לשלוח את הקישור לאימייל למכשיר נייד. כדי להשלים את הכניסה דרך אפליקציה לנייד, צריך להגדיר את האפליקציה כך שתזהה את הקישור הנכנס לאפליקציה, תנתח את קישור העומק הבסיסי ואז תשלים את הכניסה כמו שקורה בתהליך הכניסה דרך האינטרנט.
מידע נוסף על טיפול בכניסה באמצעות קישור באימייל באפליקציית Android זמין במדריך ל-Android.
במדריך לפלטפורמות של אפל מוסבר איך לטפל בכניסה באמצעות קישור באימייל באפליקציה של אפל.
קישור או אימות מחדש באמצעות קישור באימייל
אפשר גם לקשר את שיטת האימות הזו למשתמש קיים. לדוגמה, אם משתמש עבר אימות בעבר אצל ספק אחר, כמו מספר טלפון, הוא יכול להוסיף את שיטת הכניסה הזו לחשבון הקיים שלו.
ההבדל יהיה במחצית השנייה של הפעולה:
Web
import { getAuth, linkWithCredential, EmailAuthProvider } from "firebase/auth"; // Construct the email link credential from the current URL. const credential = EmailAuthProvider.credentialWithLink( email, window.location.href); // Link the credential to the current user. const auth = getAuth(); linkWithCredential(auth.currentUser, credential) .then((usercred) => { // The provider is now successfully linked. // The phone user can now sign in with their phone number or email. }) .catch((error) => { // Some error occurred. });
Web
// Construct the email link credential from the current URL. var credential = firebase.auth.EmailAuthProvider.credentialWithLink( email, window.location.href); // Link the credential to the current user. firebase.auth().currentUser.linkWithCredential(credential) .then((usercred) => { // The provider is now successfully linked. // The phone user can now sign in with their phone number or email. }) .catch((error) => { // Some error occurred. });
אפשר להשתמש בזה גם כדי לאמת מחדש משתמש עם קישור באימייל לפני שמריצים פעולה רגישה.
Web
import { getAuth, reauthenticateWithCredential, EmailAuthProvider } from "firebase/auth"; // Construct the email link credential from the current URL. const credential = EmailAuthProvider.credentialWithLink( email, window.location.href); // Re-authenticate the user with this credential. const auth = getAuth(); reauthenticateWithCredential(auth.currentUser, credential) .then((usercred) => { // The user is now successfully re-authenticated and can execute sensitive // operations. }) .catch((error) => { // Some error occurred. });
Web
// Construct the email link credential from the current URL. var credential = firebase.auth.EmailAuthProvider.credentialWithLink( email, window.location.href); // Re-authenticate the user with this credential. firebase.auth().currentUser.reauthenticateWithCredential(credential) .then((usercred) => { // The user is now successfully re-authenticated and can execute sensitive // operations. }) .catch((error) => { // Some error occurred. });
עם זאת, יכול להיות שהתהליך יסתיים במכשיר אחר שבו המשתמש המקורי לא היה מחובר, ולכן יכול להיות שהתהליך לא יושלם. במקרה כזה, יכול להיות שתוצג למשתמש שגיאה כדי לאלץ אותו לפתוח את הקישור באותו מכשיר. אפשר להעביר מצב מסוים בקישור כדי לספק מידע על סוג הפעולה ועל מזהה המשתמש (UID).
הוצאה משימוש: הבחנה בין אימייל וסיסמה לבין קישור באימייל
אם יצרתם את הפרויקט ב-15 בספטמבר 2023 או אחרי, ההגנה מפני ספירת כתובות אימייל מופעלת כברירת מחדל. התכונה הזו משפרת את האבטחה של חשבונות המשתמשים בפרויקט, אבל היא משביתה את השיטה fetchSignInMethodsForEmail(), שבעבר המלצנו להשתמש בה כדי להטמיע תהליכים שמתחילים בזיהוי.
אפשר להשבית את ההגנה מפני ספירת כתובות אימייל בפרויקט, אבל אנחנו לא ממליצים לעשות את זה.
פרטים נוספים זמינים במאמר בנושא הגנה על ספירת כתובות אימייל.
תבנית אימייל שמוגדרת כברירת מחדל לכניסה באמצעות קישור
תבנית האימייל שמוגדרת כברירת מחדל כוללת חותמת זמן בנושא ובתוכן האימייל, כדי שהאימיילים הבאים לא יכווצו לשרשור אחד והקישור לא יוסתר.
התבנית הזו רלוונטית לשפות הבאות:
| קוד | שפה |
|---|---|
| ar | ערבית |
| zh-CN | סינית (פשוטה) |
| zh-TW | סינית (מסורתית) |
| nl | הולנדית |
| en | אנגלית |
| en-GB | אנגלית (בריטניה) |
| fr | צרפתית |
| de | גרמנית |
| id [מזהה] | אינדונזית |
| it | איטלקי |
| ja | יפנית |
| ko | קוריאנית |
| pl | פולנית |
| pt-BR | פורטוגזית (ברזיל) |
| pt-PT | פורטוגזית (פורטוגל) |
| ru | רוסית |
| es | ספרדית |
| es-419 | ספרדית (אמריקה הלטינית) |
| th | תאית |
השלבים הבאים
אחרי שמשתמש נכנס לחשבון בפעם הראשונה, נוצר חשבון משתמש חדש שמקושר לפרטי הכניסה – כלומר, שם המשתמש והסיסמה, מספר הטלפון או פרטי ספק האימות – שבאמצעותם המשתמש נכנס לחשבון. החשבון החדש הזה נשמר כחלק מפרויקט Firebase, ואפשר להשתמש בו כדי לזהות משתמש בכל האפליקציות בפרויקט, בלי קשר לשיטת הכניסה של המשתמש.
-
באפליקציות, הדרך המומלצת לדעת מה סטטוס האימות של המשתמש היא להגדיר אובייקט observer ב-
Auth. אחרי כן תוכלו לקבל את פרטי הפרופיל הבסיסיים של המשתמש מאובייקטUser. ניהול משתמשים ב-Firebase Realtime Database וב-Cloud Storage Security Rules, אפשר לקבל את מזהה המשתמש הייחודי של המשתמש המחובר מהמשתנה
auth, ולהשתמש בו כדי לקבוע לאילו נתונים משתמש יכול לגשת.
אתם יכולים לאפשר למשתמשים להיכנס לאפליקציה שלכם באמצעות כמה ספקי אימות על ידי קישור פרטי כניסה של ספק אימות לחשבון משתמש קיים.
כדי להוציא משתמש מהחשבון, מתקשרים אל
signOut:
Web
import { getAuth, signOut } from "firebase/auth"; const auth = getAuth(); signOut(auth).then(() => { // Sign-out successful. }).catch((error) => { // An error happened. });
Web
firebase.auth().signOut().then(() => { // Sign-out successful. }).catch((error) => { // An error happened. });