احراز هویت چند عاملی را به برنامه وب خود اضافه کنید

اگر به Firebase Authentication with Identity Platform ارتقا داده اید، می توانید احراز هویت چند مرحله ای SMS را به برنامه وب خود اضافه کنید.

احراز هویت چند عاملی امنیت اپلیکیشن شما را افزایش می دهد. در حالی که مهاجمان اغلب رمزهای عبور و حساب های اجتماعی را به خطر می اندازند، رهگیری یک پیام متنی دشوارتر است.

قبل از شروع

  1. حداقل یک ارائه دهنده را فعال کنید که از احراز هویت چند مرحله ای پشتیبانی می کند. هر ارائه‌دهنده‌ای از MFA پشتیبانی می‌کند، به‌جز احراز هویت تلفن، احراز هویت ناشناس و Apple Game Center.

  2. مناطقی را که قصد استفاده از احراز هویت پیامکی را دارید فعال کنید. Firebase از یک خط مشی منطقه SMS کاملاً مسدود کننده استفاده می کند که به طور پیش فرض به ایجاد پروژه های شما در حالت امن تر کمک می کند.

  3. مطمئن شوید که برنامه شما ایمیل های کاربر را تأیید می کند. وزارت امور خارجه به تأیید ایمیل نیاز دارد. این امر مانع از ثبت نام عوامل مخرب در سرویسی با ایمیلی می شود که متعلق به آنها نیست و سپس با افزودن عامل دوم، مالک واقعی را قفل می کند.

استفاده از چند اجاره

اگر احراز هویت چند عاملی را برای استفاده در یک محیط چند مستاجر فعال می‌کنید، حتماً مراحل زیر را تکمیل کنید (علاوه بر بقیه دستورالعمل‌های این سند):

  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. صفحه Authentication > Sign-in را در کنسول Firebase باز کنید.

  2. در بخش Advanced ، SMS Multi-factor Authentication را فعال کنید.

    همچنین باید شماره تلفن هایی را که برنامه خود را با آنها آزمایش می کنید وارد کنید. در حالی که اختیاری است، ثبت شماره تلفن های آزمایشی قویاً توصیه می شود تا در حین توسعه ایجاد فشار نشود.

  3. اگر قبلاً دامنه برنامه خود را تأیید نکرده‌اید، آن را به فهرست مجاز در صفحه تأیید هویت > تنظیمات کنسول Firebase اضافه کنید.

انتخاب الگوی ثبت نام

می‌توانید انتخاب کنید که آیا برنامه شما به احراز هویت چند مرحله‌ای نیاز دارد یا خیر، و چگونه و چه زمانی کاربران خود را ثبت‌نام کند. برخی از الگوهای رایج عبارتند از:

  • فاکتور دوم کاربر را به عنوان بخشی از ثبت نام ثبت کنید. اگر برنامه شما نیاز به احراز هویت چند عاملی برای همه کاربران دارد، از این روش استفاده کنید.

  • برای ثبت فاکتور دوم در حین ثبت نام، یک گزینه قابل پرش ارائه دهید. برنامه‌هایی که می‌خواهند احراز هویت چندعاملی را تشویق کنند، اما نیازی به آن ندارند، ممکن است این رویکرد را ترجیح دهند.

  • به جای صفحه ثبت نام، امکان اضافه کردن فاکتور دوم را از صفحه مدیریت حساب کاربری یا نمایه کاربر فراهم کنید. این امر اصطکاک را در طول فرآیند ثبت نام به حداقل می رساند، در حالی که هنوز احراز هویت چند عاملی را برای کاربران حساس به امنیت در دسترس قرار می دهد.

  • هنگامی که کاربر می‌خواهد به ویژگی‌هایی با الزامات امنیتی افزایش یافته دسترسی پیدا کند، باید فاکتور دوم را به صورت تدریجی اضافه کنید.

تنظیم تأیید کننده reCAPTCHA

قبل از اینکه بتوانید کدهای پیامکی ارسال کنید، باید یک تأییدکننده reCAPTCHA را پیکربندی کنید. Firebase از reCAPTCHA استفاده می‌کند تا با اطمینان از اینکه درخواست‌های تأیید شماره تلفن از یکی از دامنه‌های مجاز برنامه شما می‌آیند، از سوء استفاده جلوگیری می‌کند.

شما نیازی به راه اندازی دستی مشتری reCAPTCHA ندارید. شی RecaptchaVerifier کلاینت SDK به طور خودکار هر کلید و اسرار مشتری لازم را ایجاد و مقداردهی اولیه می کند.

استفاده از reCAPTCHA نامرئی

شی RecaptchaVerifier از reCAPTCHA نامرئی پشتیبانی می کند، که اغلب می تواند کاربر را بدون نیاز به هیچ گونه تعاملی تأیید کند. برای استفاده از یک reCAPTCHA نامرئی، یک RecaptchaVerifier با پارامتر size تنظیم شده روی invisible ایجاد کنید و شناسه عنصر UI را که ثبت نام چند عاملی را شروع می‌کند، مشخص کنید:

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 با شناسه ظرف UI ایجاد کنید. همچنین می‌توانید به‌صورت اختیاری تماس‌هایی را تنظیم کنید که وقتی 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);

RecaptchaVerifier این منطق را با متد verify انتزاع می‌کند، بنابراین نیازی نیست مستقیماً متغیر 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.
      })
    

    اگرچه لازم نیست، بهترین روش این است که از قبل به کاربران اطلاع دهید که پیامک دریافت خواهند کرد و نرخ های استاندارد اعمال می شود.

  7. اگر درخواست ناموفق بود، reCAPTCHA را بازنشانی کنید، سپس مرحله قبل را تکرار کنید تا کاربر بتواند دوباره امتحان کند. توجه داشته باشید که verifyPhoneNumber() به طور خودکار reCAPTCHA را هنگامی که خطایی ایجاد می کند بازنشانی می کند، زیرا نشانه های reCAPTCHA فقط یک بار استفاده می شوند.

    Web

    recaptchaVerifier.clear();
    

    Web

    recaptchaVerifier.clear();
    
  8. پس از ارسال کد پیامک، از کاربر بخواهید که کد را تأیید کند:

    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. تکمیل ثبت نام به صورت اختیاری، می توانید یک نام نمایشی برای فاکتور دوم تعیین کنید. این برای کاربرانی که چندین عامل دوم دارند مفید است، زیرا شماره تلفن در جریان احراز هویت پنهان می‌شود (به عنوان مثال 1234*******+1).

    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);
});

تبریک می گویم! شما با موفقیت دومین فاکتور احراز هویت را برای یک کاربر ثبت کردید.

ورود کاربران با فاکتور دوم

برای ورود به یک کاربر با تأیید پیام کوتاه دو مرحله ای:

  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. پس از ارسال کد پیامک، از کاربر بخواهید که کد را تأیید کند:

    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.
    } ...
  });

تبریک می گویم! شما با موفقیت با استفاده از احراز هویت چند عاملی وارد سیستم کاربری شدید.

بعدش چی