אפשר להשתמש ב-Firebase Authentication כדי לשלוח הודעה ב-SMS לטלפון של המשתמש כדי לאפשר לו להיכנס לחשבון. המשתמש נכנס באמצעות קוד חד-פעמי שמופיע בהודעת ה-SMS.
הדרך הקלה ביותר להוסיף לאפליקציה כניסה באמצעות מספר טלפון היא להשתמש ב-FirebaseUI, שכולל ווידג'ט כניסה שמטמיע תהליכי כניסה לכניסה באמצעות מספר טלפון, וגם כניסה מבוססת-סיסמה וכניסה מאוחדת. במסמך הזה מוסבר איך מטמיעים תהליך כניסה באמצעות מספר טלפון באמצעות Firebase SDK.
לפני שמתחילים
אם עדיין לא עשיתם זאת, מעתיקים את קטע הקוד לטעינה מהמסוף Firebase לפרויקט, כפי שמתואר במאמר הוספת Firebase לפרויקט JavaScript.חששות אבטחה
אימות באמצעות מספר טלפון בלבד הוא נוח, אבל פחות מאובטח מהשיטות האחרות הזמינות, כי אפשר להעביר בקלות את הבעלות על מספר טלפון בין משתמשים. בנוסף, במכשירים עם כמה פרופילים של משתמשים, כל משתמש שיכול לקבל הודעות SMS יכול להיכנס לחשבון באמצעות מספר הטלפון של המכשיר.
אם אתם משתמשים בכניסה שמבוססת על מספר טלפון באפליקציה, כדאי להציע אותה לצד שיטות כניסה מאובטחות יותר, ולהודיע למשתמשים על הפשרות האבטחה הכרוכות בכניסה באמצעות מספר טלפון.
הפעלת הכניסה באמצעות מספר טלפון בפרויקט Firebase
כדי לאפשר למשתמשים להיכנס באמצעות SMS, קודם צריך להפעיל את שיטת הכניסה באמצעות מספר טלפון בפרויקט Firebase:
- במסוף Firebase, פותחים את הקטע Authentication.
- בדף Sign-in Method מפעילים את שיטת הכניסה Phone Number.
- באותו דף, אם הדומיין שבו האפליקציה תתארח לא מופיע בקטע דומיינים להפניה אוטומטית של 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();
שימוש ב-invisible 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
אפשר להגדיר פונקציות קריאה חוזרת (callback) באובייקט 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. לאחר מכן, מעבירים את הקוד ל-method confirm
של האובייקט ConfirmationResult
שהועברו למטפל ההשלמה של 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.
- בכרטיסייה Sign in method (שיטת כניסה), מפעילים את ספק הטלפון, אם עדיין לא עשיתם זאת.
- פותחים את התפריט הנפתח מספרי טלפון לבדיקה.
- מציינים את מספר הטלפון שרוצים לבדוק, לדוגמה: +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 יפוג אחרי זמן מה, ואז היא תיפתר שוב באופן אוטומטי. - Invisible reCAPTCHA: reCAPTCHA הנסתר לא נפתר באופן אוטומטי במהלך העיבוד, אלא בקריאה
appVerifier.verify()
או כשלוחצים על לחצן העוגן של reCAPTCHA לאחר עיכוב של חלקיק שנייה. באופן דומה, התוקף של התגובה יפוג אחרי זמן מה והיא תבוטל באופן אוטומטי רק אחרי הקריאה ל-appVerifier.verify()
או כשלוחצים שוב על הלחצן של ה-reCAPTCHA.
בכל פעם שמתבצעת פתרון של reCAPTCHA מדומה, פונקציית הקריאה החוזרת המתאימה מופעלת כצפוי עם התשובה המזויפת. אם יצוין גם מספר טלפון לקריאה חוזרת בתום התוקף, היא תופעל בתום התוקף.
השלבים הבאים
אחרי שמשתמש נכנס לחשבון בפעם הראשונה, נוצר חשבון משתמש חדש שמקושר לפרטי הכניסה – כלומר שם המשתמש והסיסמה, מספר הטלפון או פרטי ספק האימות – שבאמצעותם המשתמש נכנס לחשבון. החשבון החדש הזה מאוחסן כחלק מפרויקט 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. });