הוספת אימות רב-גורמי לאפליקציית האינטרנט

אם שדרגת ל-Firebase Authentication with Identity Platform, יש לך אפשרות להוסיף אימות רב-שלבי באמצעות SMS לאפליקציית האינטרנט.

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

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

  1. להפעיל לפחות ספק אחד שתומך באימות רב-שלבי. כל ספק תומך ב-MFA, למעט אימות טלפון, אימות אנונימי מרכז המשחקים של Apple.

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

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

שימוש בריבוי דיירים (multi-tenancy)

אם אתם מפעילים אימות רב-שלבי לשימוש multi-tenant, צריך לוודא לביצוע השלבים הבאים (בנוסף לשאר הוראות במסמך זה):

  1. במסוף Google Cloud, בוחרים את הדייר שאיתו רוצים לעבוד.

  2. בקוד, מגדירים את השדה tenantId במכונה Auth למזהה של הדייר. לדוגמה:

    Web

    import { getAuth } from "firebase/auth";
    
    const auth = getAuth(app);
    auth.tenantId = "myTenantId1";
    

    Web

    firebase.auth().tenantId = 'myTenantId1';
    

הפעלת אימות רב-שלבי

  1. פותחים את אימות > שיטת הכניסה במסוף Firebase.

  2. בקטע מתקדם, מפעילים את האפשרות אימות רב-שלבי ב-SMS.

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

  3. אם עדיין לא אישרת את הדומיין של האפליקציה, צריך להוסיף אותו להרשאה ברשימה אימות > הגדרות במסוף Firebase.

בחירת דפוס הרישום

תוכלו לבחור אם האפליקציה תדרוש אימות רב-שלבי ואיך ומתי לרשום את המשתמשים. דוגמאות לדפוסים נפוצים:

  • רישום הגורם השני של המשתמש כחלק מהרישום. שימוש בטיוטה הזו אם האפליקציה שלכם דורשת אימות רב-שלבי לכל המשתמשים.

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

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

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

הגדרת המאמת של reCAPTCHA

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

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

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

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

Web

import { RecaptchaVerifier } from "firebase/auth";

const recaptchaVerifier = new RecaptchaVerifier("sign-in-button", {
    "size": "invisible",
    "callback": function(response) {
        // reCAPTCHA solved, you can proceed with
        // phoneAuthProvider.verifyPhoneNumber(...).
        onSolvedRecaptcha();
    }
}, auth);

Web

var recaptchaVerifier = new firebase.auth.RecaptchaVerifier('sign-in-button', {
'size': 'invisible',
'callback': function(response) {
  // reCAPTCHA solved, you can proceed with phoneAuthProvider.verifyPhoneNumber(...).
  onSolvedRecaptcha();
}
});

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

כדי להשתמש בווידג'ט גלוי של reCAPTCHA, צריך ליצור רכיב HTML שיכלול הווידג'ט, ואז יוצרים אובייקט RecaptchaVerifier עם המזהה של ממשק המשתמש מאגר תגים. אפשר גם להגדיר קריאות חוזרות (callbacks) שמופעלות כאשר ה-reCAPTCHA נפתרה או שהתוקף שלו פג:

Web

import { RecaptchaVerifier } from "firebase/auth";

const recaptchaVerifier = new RecaptchaVerifier(
    "recaptcha-container",

    // Optional reCAPTCHA parameters.
    {
      "size": "normal",
      "callback": function(response) {
        // reCAPTCHA solved, you can proceed with
        // phoneAuthProvider.verifyPhoneNumber(...).
        onSolvedRecaptcha();
      },
      "expired-callback": function() {
        // Response expired. Ask user to solve reCAPTCHA again.
        // ...
      }
    }, auth
);

Web

var recaptchaVerifier = new firebase.auth.RecaptchaVerifier(
  'recaptcha-container',
  // Optional reCAPTCHA parameters.
  {
    'size': 'normal',
    'callback': function(response) {
      // reCAPTCHA solved, you can proceed with phoneAuthProvider.verifyPhoneNumber(...).
      // ...
      onSolvedRecaptcha();
    },
    'expired-callback': function() {
      // Response expired. Ask user to solve reCAPTCHA again.
      // ...
    }
  });

עיבוד מראש של ה-reCAPTCHA

לחלופין, ניתן לעבד מראש את ה-reCAPTCHA לפני שמתחילים בשני שלבים הרשמה:

Web

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

Web

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

לאחר תיקון הבעיה render(), תקבלו את מזהה הווידג'ט של reCAPTCHA, שבו תוכלו להשתמש. כדי לבצע שיחות reCAPTCHA API:

var recaptchaResponse = grecaptcha.getResponse(window.recaptchaWidgetId);

באמצעות השיטה verify, RecaptchaVerifier מסיר את הלוגיקה הזו מהקוד, כך שאין צורך לטפל במשתנה grecaptcha ישירות.

רישום של גורם שני

כדי להירשם לגורם אימות משני חדש למשתמש:

  1. מאמתים מחדש את המשתמש.

  2. מבקשים מהמשתמש להזין את מספר הטלפון שלו.

  3. מפעילים את מאמת reCAPTCHA כפי שמוצג בקטע הקודם. דלגו על השלב הזה אם כבר מוגדר מופע של ReCAPTCHAVerifier:

    Web

    import { RecaptchaVerifier } from "firebase/auth";
    
    const recaptchaVerifier = new RecaptchaVerifier('recaptcha-container-id', undefined, auth);
    

    Web

    var recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container-id');
    
  4. יצירת סשן רב-שלבי למשתמש:

    Web

    import { multiFactor } from "firebase/auth";
    
    multiFactor(user).getSession().then(function (multiFactorSession) {
        // ...
    });
    

    Web

    user.multiFactor.getSession().then(function(multiFactorSession) {
      // ...
    })
    
  5. מאתחלים אובייקט PhoneInfoOptions עם מספר הטלפון של המשתמש והסשן עם אימות רב-גורמי:

    Web

    // Specify the phone number and pass the MFA session.
    const phoneInfoOptions = {
      phoneNumber: phoneNumber,
      session: multiFactorSession
    };
    

    Web

    // Specify the phone number and pass the MFA session.
    var phoneInfoOptions = {
      phoneNumber: phoneNumber,
      session: multiFactorSession
    };
    
  6. שליחת הודעת אימות לטלפון של המשתמש:

    Web

    import { PhoneAuthProvider } from "firebase/auth";
    
    const phoneAuthProvider = new PhoneAuthProvider(auth);
    phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier)
        .then(function (verificationId) {
            // verificationId will be needed to complete enrollment.
        });
    

    Web

    var phoneAuthProvider = new firebase.auth.PhoneAuthProvider();
    // Send SMS verification code.
    return phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier)
      .then(function(verificationId) {
        // verificationId will be needed for enrollment completion.
      })
    

    אמנם זו לא חובה, אבל מומלץ להודיע למשתמשים מראש על כך הם יקבלו הודעת SMS, ויחולו התעריפים הרגילים.

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

    Web

    recaptchaVerifier.clear();
    

    Web

    recaptchaVerifier.clear();
    
  8. אחרי שליחת קוד ה-SMS, מבקשים מהמשתמש לאמת את הקוד:

    Web

    // Ask user for the verification code. Then:
    const cred = PhoneAuthProvider.credential(verificationId, verificationCode);
    

    Web

    // Ask user for the verification code. Then:
    var cred = firebase.auth.PhoneAuthProvider.credential(verificationId, verificationCode);
    
  9. מאתחלים אובייקט MultiFactorAssertion באמצעות PhoneAuthCredential:

    Web

    import { PhoneMultiFactorGenerator } from "firebase/auth";
    
    const multiFactorAssertion = PhoneMultiFactorGenerator.assertion(cred);
    

    Web

    var multiFactorAssertion = firebase.auth.PhoneMultiFactorGenerator.assertion(cred);
    
  10. משלימים את תהליך ההרשמה. אפשר גם לציין שם לתצוגה עבור גורם שני. זה שימושי למשתמשים שיש להם הרבה גורמים שמשפיעים על השנייה, במקרה של אנונימיזציה של מספר הטלפון בתהליך האימות (במקרה של לדוגמה, +1******1234).

    Web

    // Complete enrollment. This will update the underlying tokens
    // and trigger ID token change listener.
    multiFactor(user).enroll(multiFactorAssertion, "My personal phone number");
    

    Web

    // Complete enrollment. This will update the underlying tokens
    // and trigger ID token change listener.
    user.multiFactor.enroll(multiFactorAssertion, 'My personal phone number');
    

הקוד הבא מציג דוגמה מלאה לרישום של גורם שני:

Web

import {
    multiFactor, PhoneAuthProvider, PhoneMultiFactorGenerator,
    RecaptchaVerifier
} from "firebase/auth";

const recaptchaVerifier = new RecaptchaVerifier('recaptcha-container-id', undefined, auth);
multiFactor(user).getSession()
    .then(function (multiFactorSession) {
        // Specify the phone number and pass the MFA session.
        const phoneInfoOptions = {
            phoneNumber: phoneNumber,
            session: multiFactorSession
        };

        const phoneAuthProvider = new PhoneAuthProvider(auth);

        // Send SMS verification code.
        return phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier);
    }).then(function (verificationId) {
        // Ask user for the verification code. Then:
        const cred = PhoneAuthProvider.credential(verificationId, verificationCode);
        const multiFactorAssertion = PhoneMultiFactorGenerator.assertion(cred);

        // Complete enrollment.
        return multiFactor(user).enroll(multiFactorAssertion, mfaDisplayName);
    });

Web

var recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container-id');
user.multiFactor.getSession().then(function(multiFactorSession) {
  // Specify the phone number and pass the MFA session.
  var phoneInfoOptions = {
    phoneNumber: phoneNumber,
    session: multiFactorSession
  };
  var phoneAuthProvider = new firebase.auth.PhoneAuthProvider();
  // Send SMS verification code.
  return phoneAuthProvider.verifyPhoneNumber(
      phoneInfoOptions, recaptchaVerifier);
})
.then(function(verificationId) {
  // Ask user for the verification code.
  var cred = firebase.auth.PhoneAuthProvider.credential(verificationId, verificationCode);
  var multiFactorAssertion = firebase.auth.PhoneMultiFactorGenerator.assertion(cred);
  // Complete enrollment.
  return user.multiFactor.enroll(multiFactorAssertion, mfaDisplayName);
});

כל הכבוד! רשמת בהצלחה גורם אימות שני עבור משתמש.

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

כדי להיכנס למשתמש באמצעות אימות דו-שלבי באמצעות SMS:

  1. מכניסים את המשתמש עם הגורם הראשון, ואז מקבלים את שגיאה אחת (auth/multi-factor-auth-required). השגיאה הזו מכילה פותר, רמזים לגבי הגורמים השניים המאומתים וסשן בסיסי שמוכיח שהמשתמש אומת בהצלחה באמצעות הגורם הראשון.

    לדוגמה, אם הגורם הראשון שגרם למשתמש הוא כתובת אימייל וסיסמה:

    Web

    import { getAuth, getMultiFactorResolver} from "firebase/auth";
    
    const auth = getAuth();
    signInWithEmailAndPassword(auth, email, password)
        .then(function (userCredential) {
            // User successfully signed in and is not enrolled with a second factor.
        })
        .catch(function (error) {
            if (error.code == 'auth/multi-factor-auth-required') {
                // The user is a multi-factor user. Second factor challenge is required.
                resolver = getMultiFactorResolver(auth, error);
                // ...
            } else if (error.code == 'auth/wrong-password') {
                // Handle other errors such as wrong password.
            }
    });
    

    Web

    firebase.auth().signInWithEmailAndPassword(email, password)
      .then(function(userCredential) {
        // User successfully signed in and is not enrolled with a second factor.
      })
      .catch(function(error) {
        if (error.code == 'auth/multi-factor-auth-required') {
          // The user is a multi-factor user. Second factor challenge is required.
          resolver = error.resolver;
          // ...
        } else if (error.code == 'auth/wrong-password') {
          // Handle other errors such as wrong password.
        } ...
      });
    

    אם הגורם הראשון של המשתמש הוא ספק מאוחד, כמו OAuth,‏ SAML או OIDC, צריך לזהות את השגיאה אחרי הקריאה ל-signInWithPopup() או ל-signInWithRedirect().

  2. אם למשתמש יש כמה גורמים משניים רשומים, שואלים אותו איזה כדי להשתמש:

    Web

    // Ask user which second factor to use.
    // You can get the masked phone number via resolver.hints[selectedIndex].phoneNumber
    // You can get the display name via resolver.hints[selectedIndex].displayName
    
    if (resolver.hints[selectedIndex].factorId ===
        PhoneMultiFactorGenerator.FACTOR_ID) {
        // User selected a phone second factor.
        // ...
    } else if (resolver.hints[selectedIndex].factorId ===
               TotpMultiFactorGenerator.FACTOR_ID) {
        // User selected a TOTP second factor.
        // ...
    } else {
        // Unsupported second factor.
    }
    

    Web

    // Ask user which second factor to use.
    // You can get the masked phone number via resolver.hints[selectedIndex].phoneNumber
    // You can get the display name via resolver.hints[selectedIndex].displayName
    if (resolver.hints[selectedIndex].factorId === firebase.auth.PhoneMultiFactorGenerator.FACTOR_ID) {
      // User selected a phone second factor.
      // ...
    } else if (resolver.hints[selectedIndex].factorId === firebase.auth.TotpMultiFactorGenerator.FACTOR_ID) {
      // User selected a TOTP second factor.
      // ...
    } else {
      // Unsupported second factor.
    }
    
  3. מפעילים את מאמת reCAPTCHA כפי שמוצג בקטע הקודם. דלגו על השלב הזה אם כבר מוגדר מופע של ReCAPTCHAVerifier:

    Web

    import { RecaptchaVerifier } from "firebase/auth";
    
    recaptchaVerifier = new RecaptchaVerifier('recaptcha-container-id', undefined, auth);
    

    Web

    var recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container-id');
    
  4. אתחול אובייקט PhoneInfoOptions עם מספר הטלפון של המשתמש וגם את הסשן הרב-שלבי. הערכים האלה נמצאים בפונקציה resolver האובייקט הועבר לשגיאה auth/multi-factor-auth-required:

    Web

    const phoneInfoOptions = {
        multiFactorHint: resolver.hints[selectedIndex],
        session: resolver.session
    };
    

    Web

    var phoneInfoOptions = {
      multiFactorHint: resolver.hints[selectedIndex],
      session: resolver.session
    };
    
  5. שליחת הודעת אימות לטלפון של המשתמש:

    Web

    // Send SMS verification code.
    const phoneAuthProvider = new PhoneAuthProvider(auth);
    phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier)
        .then(function (verificationId) {
            // verificationId will be needed for sign-in completion.
        });
    

    Web

    var phoneAuthProvider = new firebase.auth.PhoneAuthProvider();
    // Send SMS verification code.
    return phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier)
      .then(function(verificationId) {
        // verificationId will be needed for sign-in completion.
      })
    
  6. אם הבקשה נכשלת, מאפסים את ה-reCAPTCHA ואז חוזרים על השלב הקודם כדי שהמשתמש יוכל לנסות שוב:

    Web

    recaptchaVerifier.clear();
    

    Web

    recaptchaVerifier.clear();
    
  7. לאחר שליחת קוד ה-SMS, מבקשים מהמשתמש לאמת את הקוד:

    Web

    const cred = PhoneAuthProvider.credential(verificationId, verificationCode);
    

    Web

    // Ask user for the verification code. Then:
    var cred = firebase.auth.PhoneAuthProvider.credential(verificationId, verificationCode);
    
  8. מאתחלים אובייקט MultiFactorAssertion באמצעות PhoneAuthCredential:

    Web

    const multiFactorAssertion = PhoneMultiFactorGenerator.assertion(cred);
    

    Web

    var multiFactorAssertion = firebase.auth.PhoneMultiFactorGenerator.assertion(cred);
    
  9. צריך להפעיל את resolver.resolveSignIn() כדי להשלים את האימות המשני. אחרי זה תוכלו לגשת לתוצאת הכניסה המקורית, שכוללת את נתונים ופרטי כניסה לאימות שספציפיים לספק רגיל:

    Web

    // Complete sign-in. This will also trigger the Auth state listeners.
    resolver.resolveSignIn(multiFactorAssertion)
        .then(function (userCredential) {
            // userCredential will also contain the user, additionalUserInfo, optional
            // credential (null for email/password) associated with the first factor sign-in.
    
            // For example, if the user signed in with Google as a first factor,
            // userCredential.additionalUserInfo will contain data related to Google
            // provider that the user signed in with.
            // - user.credential contains the Google OAuth credential.
            // - user.credential.accessToken contains the Google OAuth access token.
            // - user.credential.idToken contains the Google OAuth ID token.
        });
    

    Web

    // Complete sign-in. This will also trigger the Auth state listeners.
    resolver.resolveSignIn(multiFactorAssertion)
      .then(function(userCredential) {
        // userCredential will also contain the user, additionalUserInfo, optional
        // credential (null for email/password) associated with the first factor sign-in.
        // For example, if the user signed in with Google as a first factor,
        // userCredential.additionalUserInfo will contain data related to Google provider that
        // the user signed in with.
        // user.credential contains the Google OAuth credential.
        // user.credential.accessToken contains the Google OAuth access token.
        // user.credential.idToken contains the Google OAuth ID token.
      });
    

הקוד הבא מציג דוגמה מלאה לכניסה לחשבון של משתמש רב-שלבי:

Web

import {
    getAuth,
    getMultiFactorResolver,
    PhoneAuthProvider,
    PhoneMultiFactorGenerator,
    RecaptchaVerifier,
    signInWithEmailAndPassword
} from "firebase/auth";

const recaptchaVerifier = new RecaptchaVerifier('recaptcha-container-id', undefined, auth);

const auth = getAuth();
signInWithEmailAndPassword(auth, email, password)
    .then(function (userCredential) {
        // User is not enrolled with a second factor and is successfully
        // signed in.
        // ...
    })
    .catch(function (error) {
        if (error.code == 'auth/multi-factor-auth-required') {
            const resolver = getMultiFactorResolver(auth, error);
            // Ask user which second factor to use.
            if (resolver.hints[selectedIndex].factorId ===
                PhoneMultiFactorGenerator.FACTOR_ID) {
                const phoneInfoOptions = {
                    multiFactorHint: resolver.hints[selectedIndex],
                    session: resolver.session
                };
                const phoneAuthProvider = new PhoneAuthProvider(auth);
                // Send SMS verification code
                return phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier)
                    .then(function (verificationId) {
                        // Ask user for the SMS verification code. Then:
                        const cred = PhoneAuthProvider.credential(
                            verificationId, verificationCode);
                        const multiFactorAssertion =
                            PhoneMultiFactorGenerator.assertion(cred);
                        // Complete sign-in.
                        return resolver.resolveSignIn(multiFactorAssertion)
                    })
                    .then(function (userCredential) {
                        // User successfully signed in with the second factor phone number.
                    });
            } else if (resolver.hints[selectedIndex].factorId ===
                       TotpMultiFactorGenerator.FACTOR_ID) {
                // Handle TOTP MFA.
                // ...
            } else {
                // Unsupported second factor.
            }
        } else if (error.code == 'auth/wrong-password') {
            // Handle other errors such as wrong password.
        }
    });

Web

var resolver;
firebase.auth().signInWithEmailAndPassword(email, password)
  .then(function(userCredential) {
    // User is not enrolled with a second factor and is successfully signed in.
    // ...
  })
  .catch(function(error) {
    if (error.code == 'auth/multi-factor-auth-required') {
      resolver = error.resolver;
      // Ask user which second factor to use.
      if (resolver.hints[selectedIndex].factorId ===
          firebase.auth.PhoneMultiFactorGenerator.FACTOR_ID) {
        var phoneInfoOptions = {
          multiFactorHint: resolver.hints[selectedIndex],
          session: resolver.session
        };
        var phoneAuthProvider = new firebase.auth.PhoneAuthProvider();
        // Send SMS verification code
        return phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier)
          .then(function(verificationId) {
            // Ask user for the SMS verification code.
            var cred = firebase.auth.PhoneAuthProvider.credential(
                verificationId, verificationCode);
            var multiFactorAssertion =
                firebase.auth.PhoneMultiFactorGenerator.assertion(cred);
            // Complete sign-in.
            return resolver.resolveSignIn(multiFactorAssertion)
          })
          .then(function(userCredential) {
            // User successfully signed in with the second factor phone number.
          });
      } else if (resolver.hints[selectedIndex].factorId ===
        firebase.auth.TotpMultiFactorGenerator.FACTOR_ID) {
        // Handle TOTP MFA.
        // ...
      } else {
        // Unsupported second factor.
      }
    } else if (error.code == 'auth/wrong-password') {
      // Handle other errors such as wrong password.
    } ...
  });

כל הכבוד! התחברתם בהצלחה למשתמש באמצעות אימות רב-גורמי.

המאמרים הבאים