אימות עם Firebase באמצעות מספר טלפון באמצעות JavaScript

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

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

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

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

בעיות אבטחה

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

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

הפעלת כניסה באמצעות מספר טלפון בפרויקט Firebase

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

  1. במסוף Firebase, עוברים אל Security (אבטחה) > Authentication (אימות).
  2. בכרטיסייה שיטת התחברות, מפעילים את ספק הכניסה Phone (טלפון).
  3. מגדירים מדיניות לגבי האזורים שרוצים לאפשר או לאסור שליחת הודעות SMS אליהם. הגדרת מדיניות אזורית לגבי הודעות SMS יכולה לעזור להגן על האפליקציות מפני ניצול לרעה של הודעות SMS. בפרויקטים חדשים, מדיניות ברירת המחדל לא מאפשרת שימוש באזורים.
    1. במסוף Firebase, עוברים אל Security (אבטחה) > Authentication (אימות) > הכרטיסייה Settings (הגדרות).
    2. בקטע SMS region policy, מגדירים את המדיניות לגבי אזורים גיאוגרפיים לאחסון נתונים של SMS.
  4. אם עדיין לא עשיתם את זה, צריך לתת הרשאה לדומיין של האפליקציה:
    1. במסוף Firebase, עוברים אל Security (אבטחה) > Authentication (אימות) > הכרטיסייה Settings (הגדרות).
    2. בקטע דומיינים מורשים, לוחצים על הוספת דומיין ומוסיפים את הדומיין.

    הערה: אי אפשר להשתמש ב-localhost כדומיין מארח לצורך אימות טלפוני.

הגדרת כלי האימות reCAPTCHA

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

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

האובייקט RecaptchaVerifier תומך ב-invisible reCAPTCHA, שלרוב יכול לאמת את המשתמש בלי לדרוש ממנו לבצע פעולה כלשהי, וגם בווידג'ט reCAPTCHA, שתמיד דורש אינטראקציה של המשתמש כדי להשלים את האימות בהצלחה.

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

Web

import { getAuth } from "firebase/auth";

const auth = getAuth();
auth.languageCode = 'it';
// To apply the default browser preference instead of explicitly setting it.
// auth.useDeviceLanguage();

Web

firebase.auth().languageCode = 'it';
// To apply the default browser preference instead of explicitly setting it.
// firebase.auth().useDeviceLanguage();

שימוש ב-reCAPTCHA בלתי נראה

כדי להשתמש ב-reCAPTCHA בלתי נראה, יוצרים אובייקט RecaptchaVerifier עם הפרמטר size שמוגדר לערך invisible, ומציינים את המזהה של הלחצן לשליחת טופס הכניסה. לדוגמה:

Web

import { getAuth, RecaptchaVerifier } from "firebase/auth";

const auth = getAuth();
window.recaptchaVerifier = new RecaptchaVerifier(auth, 'sign-in-button', {
  'size': 'invisible',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    onSignInSubmit();
  }
});

Web

window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('sign-in-button', {
  'size': 'invisible',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    onSignInSubmit();
  }
});

שימוש בווידג'ט reCAPTCHA

כדי להשתמש בווידג'ט reCAPTCHA גלוי, צריך ליצור רכיב בדף שיכיל את הווידג'ט, ואז ליצור אובייקט RecaptchaVerifier ולציין את המזהה של הקונטיינר. לדוגמה:

Web

import { getAuth, RecaptchaVerifier } from "firebase/auth";

const auth = getAuth();
window.recaptchaVerifier = new RecaptchaVerifier(auth, 'recaptcha-container', {});

Web

window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container');

אופציונלי: מציינים פרמטרים של reCAPTCHA

אפשר להגדיר פונקציות קריאה חוזרת באובייקט RecaptchaVerifier שמופעלות כשהמשתמש פותר את reCAPTCHA או כשתוקף ה-reCAPTCHA פג לפני שהמשתמש שולח את הטופס:

Web

import { getAuth, RecaptchaVerifier } from "firebase/auth";

const auth = getAuth();
window.recaptchaVerifier = new RecaptchaVerifier(auth, 'recaptcha-container', {
  'size': 'normal',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    // ...
  },
  'expired-callback': () => {
    // Response expired. Ask user to solve reCAPTCHA again.
    // ...
  }
});

Web

window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container', {
  'size': 'normal',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    // ...
  },
  'expired-callback': () => {
    // Response expired. Ask user to solve reCAPTCHA again.
    // ...
  }
});

אופציונלי: טרום-רינדור של reCAPTCHA

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

Web

recaptchaVerifier.render().then((widgetId) => {
  window.recaptchaWidgetId = widgetId;
});

Web

recaptchaVerifier.render().then((widgetId) => {
  window.recaptchaWidgetId = widgetId;
});

אחרי ש-render נפתר, מקבלים את מזהה הווידג'ט של reCAPTCHA, שאפשר להשתמש בו כדי לבצע קריאות ל-API של reCAPTCHA:

Web

const recaptchaResponse = grecaptcha.getResponse(recaptchaWidgetId);

Web

const recaptchaResponse = grecaptcha.getResponse(recaptchaWidgetId);

שליחת קוד אימות לטלפון של המשתמש

כדי להתחיל את תהליך הכניסה באמצעות מספר טלפון, מציגים למשתמש ממשק שמבקש ממנו לספק את מספר הטלפון שלו, ואז קוראים ל-signInWithPhoneNumber כדי לבקש מ-Firebase לשלוח קוד אימות לטלפון של המשתמש באמצעות SMS:

  1. קבלת מספר הטלפון של המשתמש.

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

  2. מתקשרים אל signInWithPhoneNumber ומעבירים אליו את מספר הטלפון של המשתמש ואת RecaptchaVerifier שיצרתם קודם.

    Web

    import { getAuth, signInWithPhoneNumber } from "firebase/auth";
    
    const phoneNumber = getPhoneNumberFromUserInput();
    const appVerifier = window.recaptchaVerifier;
    
    const auth = getAuth();
    signInWithPhoneNumber(auth, phoneNumber, appVerifier)
        .then((confirmationResult) => {
          // SMS sent. Prompt user to type the code from the message, then sign the
          // user in with confirmationResult.confirm(code).
          window.confirmationResult = confirmationResult;
          // ...
        }).catch((error) => {
          // Error; SMS not sent
          // ...
        });

    Web

    const phoneNumber = getPhoneNumberFromUserInput();
    const appVerifier = window.recaptchaVerifier;
    firebase.auth().signInWithPhoneNumber(phoneNumber, appVerifier)
        .then((confirmationResult) => {
          // SMS sent. Prompt user to type the code from the message, then sign the
          // user in with confirmationResult.confirm(code).
          window.confirmationResult = confirmationResult;
          // ...
        }).catch((error) => {
          // Error; SMS not sent
          // ...
        });
    אם הפונקציה signInWithPhoneNumber מחזירה שגיאה, צריך לאפס את reCAPTCHA כדי שהמשתמש יוכל לנסות שוב:
    ‫
    grecaptcha.reset(window.recaptchaWidgetId);
    
    // Or, if you haven't stored the widget ID:
    window.recaptchaVerifier.render().then(function(widgetId) {
      grecaptcha.reset(widgetId);
    });

השיטה signInWithPhoneNumber מציגה למשתמש את מבחן reCAPTCHA, ואם המשתמש עובר את המבחן, היא מבקשת מ-Firebase Authentication לשלוח הודעת SMS עם קוד אימות לטלפון של המשתמש.

כניסה של המשתמש באמצעות קוד האימות

אחרי שהשיחה עם signInWithPhoneNumber תסתיים בהצלחה, תציג למשתמש הנחיה להקליד את קוד האימות שהוא קיבל בהודעת SMS. לאחר מכן, נכנסים לחשבון של המשתמש על ידי העברת הקוד לשיטת confirm של אובייקט ConfirmationResult שהועבר ל-handler של signInWithPhoneNumber (כלומר, לבלוק then שלו). לדוגמה:

Web

const code = getCodeFromUserInput();
confirmationResult.confirm(code).then((result) => {
  // User signed in successfully.
  const user = result.user;
  // ...
}).catch((error) => {
  // User couldn't sign in (bad verification code?)
  // ...
});

Web

const code = getCodeFromUserInput();
confirmationResult.confirm(code).then((result) => {
  // User signed in successfully.
  const user = result.user;
  // ...
}).catch((error) => {
  // User couldn't sign in (bad verification code?)
  // ...
});

אם הקריאה אל confirm הצליחה, המשתמש נכנס בהצלחה לחשבון.

אחזור אובייקט ביניים של AuthCredential

אם אתם צריכים לקבל אובייקט AuthCredential עבור החשבון של המשתמש, צריך להעביר את קוד האימות מתוצאת האישור ואת קוד האימות אל PhoneAuthProvider.credential במקום להתקשר אל confirm:

var credential = firebase.auth.PhoneAuthProvider.credential(confirmationResult.verificationId, code);

לאחר מכן, תוכלו להשתמש בפרטי הכניסה כדי להיכנס לחשבון של המשתמש:

firebase.auth().signInWithCredential(credential);

בדיקה באמצעות מספרי טלפון פיקטיביים

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

  • בדיקת אימות של מספר טלפון בלי לנכות מהמכסה שלכם.
  • בדיקת אימות של מספר טלפון בלי לשלוח הודעת SMS בפועל.
  • להריץ בדיקות עוקבות עם אותו מספר טלפון בלי שהמערכת תגביל את קצב הבקשות. זה מצמצם את הסיכון לדחייה במהלך תהליך הבדיקה בחנות האפליקציות, אם הבודק משתמש באותו מספר טלפון לבדיקה.
  • אפשר לבצע בדיקות בקלות בסביבות פיתוח בלי מאמץ נוסף, למשל לפתח באמולטור iOS או באמולטור Android בלי Google Play Services.
  • לכתוב בדיקות שילוב בלי להיחסם על ידי בדיקות אבטחה שבדרך כלל מופעלות על מספרי טלפון אמיתיים בסביבת ייצור.

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

  1. חשוב לוודא שאתם משתמשים במספרי טלפון שהם באמת פיקטיביים, ושלא קיימים כבר. Firebase Authentication לא מאפשר להגדיר מספרי טלפון קיימים שמשמשים משתמשים אמיתיים כמספרי בדיקה. אפשרות אחת היא להשתמש במספרי טלפון לבדיקה בארה"ב שמתחילים בקידומת 555, למשל: +1 650-555-3434
  2. מספרי הטלפון צריכים להיות בפורמט הנכון מבחינת האורך ומגבלות אחרות. המספרים האלה עדיין יעברו את אותו תהליך אימות כמו מספר טלפון של משתמש אמיתי.
  3. אפשר להוסיף עד 10 מספרי טלפון לפיתוח.
  4. להשתמש במספרי טלפון או בקודים לבדיקה שקשה לנחש ולשנות אותם בתדירות גבוהה.

יצירת מספרי טלפון וקודי אימות פיקטיביים

  1. במסוף Firebase, עוברים אל Security (אבטחה) > Authentication (אימות).
  2. בכרטיסייה שיטת הכניסה, מפעילים את ספק הכניסה טלפון אם עדיין לא עשיתם זאת.
  3. מרחיבים את הקטע מספרי טלפון לבדיקה.
  4. מזינים את מספר הטלפון שרוצים לבדוק, לדוגמה: +1 650-555-3434.
  5. מזינים את קוד האימות בן 6 הספרות שקיבלתם עבור המספר הספציפי הזה, לדוגמה: 654321.
  6. לוחצים על הוספה ליד כל מספר. אם צריך, אפשר למחוק את מספר הטלפון ואת הקוד שלו. כדי לעשות את זה, מעבירים את העכבר מעל השורה המתאימה ולוחצים על סמל הפח.

בדיקה ידנית

אתם יכולים להתחיל להשתמש במספר טלפון פיקטיבי באפליקציה שלכם באופן ישיר. כך תוכלו לבצע בדיקות ידניות בשלבי הפיתוח בלי להיתקל בבעיות שקשורות למכסת השימוש או להגבלת קצב הבקשות. אפשר גם לבצע בדיקה ישירות מסימולטור iOS או מאמולטור Android בלי ש-Google Play Services מותקן.

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

בסיום הכניסה, נוצר משתמש Firebase עם מספר הטלפון הזה. המשתמש מתנהג כמו משתמש עם מספר טלפון אמיתי, ויש לו את אותן תכונות. הוא יכול לגשת אל Realtime Database/Cloud Firestore ואל שירותים אחרים באותה דרך. האסימון של מזהה המשתמש שנוצר במהלך התהליך הזה כולל את אותה חתימה כמו משתמש עם מספר טלפון אמיתי.

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

בדיקות שילוב

בנוסף לבדיקות ידניות, Firebase Authentication מספק ממשקי API שיכולים לעזור לכם לכתוב בדיקות שילוב לבדיקת אימות טלפוני. ממשקי ה-API האלה משביתים את אימות האפליקציה על ידי השבתת הדרישה של reCAPTCHA באינטרנט ושל התראות פוש שקטות ב-iOS. כך אפשר לבצע בדיקות אוטומטיות בתהליכים האלה, וקל יותר להטמיע אותן. בנוסף, הם עוזרים לספק את היכולת לבדוק תהליכי אימות מיידיים ב-Android.

באינטרנט, מגדירים את appVerificationDisabledForTesting ל-true לפני העיבוד של firebase.auth.RecaptchaVerifier. הפעולה הזו פותרת את ה-reCAPTCHA באופן אוטומטי, כך שאתם יכולים להזין את מספר הטלפון בלי לפתור אותו באופן ידני. הערה: גם אם reCAPTCHA מושבת, אם תשתמשו במספר טלפון אמיתי, לא תוכלו להשלים את הכניסה. אפשר להשתמש ב-API הזה רק עם מספרי טלפון פיקטיביים.

// Turn off phone auth app verification.
firebase.auth().settings.appVerificationDisabledForTesting = true;

var phoneNumber = "+16505554567";
var testVerificationCode = "123456";

// This will render a fake reCAPTCHA as appVerificationDisabledForTesting is true.
// This will resolve after rendering without app verification.
var appVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container');
// signInWithPhoneNumber will call appVerifier.verify() which will resolve with a fake
// reCAPTCHA response.
firebase.auth().signInWithPhoneNumber(phoneNumber, appVerifier)
    .then(function (confirmationResult) {
      // confirmationResult can resolve with the fictional testVerificationCode above.
      return confirmationResult.confirm(testVerificationCode)
    }).catch(function (error) {
      // Error; SMS not sent
      // ...
    });

מאמתים גלויים ובלתי נראים של אפליקציות reCAPTCHA מדומות מתנהגים באופן שונה כשהאימות של האפליקציה מושבת:

  • ‫reCAPTCHA גלוי: כש-reCAPTCHA הגלוי מוצג באמצעות appVerifier.render(), הוא נפתר אוטומטית אחרי השהיה של חלקיק שנייה. זה שווה ערך ללחיצה של משתמש על reCAPTCHA מיד אחרי העיבוד. התוקף של התגובה ל-reCAPTCHA יפוג אחרי זמן מה, ואז הבעיה תיפתר שוב באופן אוטומטי.
  • ‫reCAPTCHA בלתי נראה: ה-reCAPTCHA הבלתי נראה לא נפתר אוטומטית בזמן העיבוד, אלא בזמן הקריאה ל-appVerifier.verify() או כשלוחצים על לחצן העוגן של ה-reCAPTCHA אחרי השהיה של חלקיק שנייה. באופן דומה, תוקף התגובה יפוג אחרי זמן מסוים, והיא תיפתר אוטומטית רק אחרי הקריאה ל-appVerifier.verify() או כשלוחצים שוב על לחצן העוגן של reCAPTCHA.

בכל פעם שמתבצעת התאמה של reCAPTCHA מדומה, מופעלת פונקציית הקריאה החוזרת התואמת כמצופה עם התשובה המזויפת. אם מציינים גם פונקציית קריאה חוזרת (callback) לתפוגה, היא תופעל כשהתוקף יפוג.

השלבים הבאים

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

  • הדרך המומלצת לדעת מה סטטוס האימות של המשתמש באפליקציות היא להגדיר אובייקט Auth של צופה. אחרי זה אפשר לקבל את פרטי הפרופיל הבסיסיים של המשתמש מאובייקט User. איך מנהלים משתמשים

  • בFirebase Realtime Database ובCloud Storage כללי האבטחה, אפשר לקבל את מזהה המשתמש הייחודי של המשתמש המחובר מהמשתנה 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.
});