אתם יכולים להשתמש ב-Firebase Authentication כדי להכניס משתמש לחשבון על ידי שליחת הודעת SMS לטלפון של המשתמש. המשתמש נכנס לחשבון באמצעות קוד חד-פעמי שמופיע בהודעת ה-SMS.
הדרך הכי קלה להוסיף לאפליקציה כניסה באמצעות מספר טלפון היא באמצעות FirebaseUI, שכולל ווידג'ט כניסה שאפשר להוסיף בקלות ומיישם תהליכי כניסה באמצעות מספר טלפון, וגם כניסה באמצעות סיסמה וכניסה מאוחדת. במאמר הזה מוסבר איך להטמיע תהליך כניסה באמצעות מספר טלפון באמצעות Firebase SDK.
לפני שמתחילים
אם עדיין לא עשיתם זאת, מעתיקים את קטע הקוד לאתחול מFirebase המסוף לפרויקט, כמו שמתואר במאמר הוספת Firebase לפרויקט JavaScript.בעיות אבטחה
אימות באמצעות מספר טלפון בלבד הוא נוח, אבל פחות מאובטח מהשיטות האחרות שזמינות, כי אפשר להעביר בקלות את הבעלות על מספר טלפון ממשתמש אחד למשתמש אחר. בנוסף, במכשירים עם כמה פרופילי משתמשים, כל משתמש שיכול לקבל הודעות SMS יכול להיכנס לחשבון באמצעות מספר הטלפון של המכשיר.
אם אתם משתמשים באפליקציה שלכם בכניסה שמבוססת על מספר טלפון, אתם צריכים להציע אותה לצד שיטות כניסה מאובטחות יותר, וליידע את המשתמשים לגבי הפשרות בנושא אבטחה שקשורות לשימוש בכניסה באמצעות מספר טלפון.
הפעלת כניסה באמצעות מספר טלפון בפרויקט Firebase
כדי לאפשר למשתמשים להיכנס באמצעות SMS, קודם צריך להפעיל את שיטת הכניסה באמצעות מספר טלפון בפרויקט Firebase:
- במסוף Firebase, פותחים את הקטע Authentication.
- בדף שיטת הכניסה, מפעילים את שיטת הכניסה באמצעות מספר טלפון.
- בדף הגדרות, מגדירים מדיניות לגבי האזורים שרוצים לאפשר או לא לאפשר בהם שליחת הודעות SMS. בפרויקטים חדשים, מדיניות ברירת המחדל לא מאפשרת שימוש באזורים.
- באותו דף, אם הדומיין שיארח את האפליקציה לא מופיע בקטע דומיינים להפניה אוטומטית של OAuth, מוסיפים את הדומיין. הערה: אי אפשר להשתמש ב-localhost כדומיין מתארח לצורך אימות טלפוני.
הגדרת מאמת reCAPTCHA
כדי לאפשר למשתמשים להיכנס באמצעות מספרי הטלפון שלהם, צריך להגדיר את כלי האימות reCAPTCHA של Firebase. Firebase משתמשת ב-reCAPTCHA כדי למנוע התנהלות פוגעת, למשל כדי לוודא שהבקשה לאימות מספר הטלפון מגיעה מאחד מהדומיינים המותרים של האפליקציה.
אין צורך להגדיר לקוח reCAPTCHA באופן ידני. כשמשתמשים באובייקט RecaptchaVerifier של Firebase SDK, Firebase יוצר ומטפל באופן אוטומטי בכל המפתחות והסודות הנדרשים של הלקוח.
אובייקט RecaptchaVerifier תומך ב-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, שאפשר להשתמש בו כדי לבצע קריאות ל-reCAPTCHA API:
Web
const recaptchaResponse = grecaptcha.getResponse(recaptchaWidgetId);
Web
const recaptchaResponse = grecaptcha.getResponse(recaptchaWidgetId);
שליחת קוד אימות לטלפון של המשתמש
כדי להתחיל את תהליך הכניסה באמצעות מספר טלפון, מציגים למשתמש ממשק שמבקש ממנו לספק את מספר הטלפון שלו, ואז קוראים ל-signInWithPhoneNumber כדי לבקש מ-Firebase לשלוח קוד אימות לטלפון של המשתמש באמצעות SMS:
-
קבלת מספר הטלפון של המשתמש.
הדרישות המשפטיות משתנות, אבל כדאי להודיע למשתמשים שאם הם משתמשים בכניסה באמצעות הטלפון, יכול להיות שהם יקבלו הודעת SMS לאימות, ושחלים עליהם תעריפים רגילים.
- מתקשרים אל
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.
- לכתוב בדיקות שילוב בלי להיחסם על ידי בדיקות אבטחה שבדרך כלל מופעלות על מספרי טלפון אמיתיים בסביבת ייצור.
מספרי טלפון פיקטיביים צריכים לעמוד בדרישות הבאות:
- חשוב לוודא שאתם משתמשים במספרי טלפון שהם באמת פיקטיביים ולא קיימים. Firebase Authentication לא מאפשר להגדיר מספרי טלפון קיימים שמשמשים משתמשים אמיתיים כמספרי בדיקה. אפשרות אחת היא להשתמש במספרים עם הקידומת 555 כמספרי טלפון לבדיקה בארה"ב, לדוגמה: +1 650-555-3434
- מספרי הטלפון צריכים להיות בפורמט הנכון מבחינת אורך ומגבלות אחרות. המספרים האלה עדיין יעברו את אותו תהליך אימות כמו מספר טלפון של משתמש אמיתי.
- אפשר להוסיף עד 10 מספרי טלפון לפיתוח.
- להשתמש במספרי טלפון או בקודים לבדיקה שקשה לנחש ולשנות אותם בתדירות גבוהה.
יצירת מספרי טלפון וקודי אימות פיקטיביים
- במסוף Firebase, פותחים את הקטע Authentication.
- בכרטיסייה שיטת הכניסה, מפעילים את ספק הטלפון אם עדיין לא עשיתם זאת.
- פותחים את התפריט הנפתח מספרי טלפון לבדיקה.
- מזינים את מספר הטלפון שרוצים לבדוק, לדוגמה: +1 650-555-3434.
- מזינים את קוד האימות בן 6 הספרות שקיבלתם למספר הספציפי הזה, לדוגמה: 654321.
- מוסיפים את המספר. אם צריך, אפשר למחוק את מספר הטלפון ואת הקוד שלו. כדי לעשות זאת, מעבירים את העכבר מעל השורה המתאימה ולוחצים על סמל האשפה.
בדיקה ידנית
אתם יכולים להתחיל להשתמש במספר טלפון פיקטיבי באפליקציה שלכם באופן ישיר. כך תוכלו לבצע בדיקות ידניות בשלבי הפיתוח בלי להיתקל בבעיות שקשורות למכסת השימוש או להגבלת קצב הבקשות. אפשר גם לבצע בדיקה ישירות מסימולטור 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. });