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

اگر به Firebase Authentication با Identity Platform ارتقا داده اید، می توانید احراز هویت چند مرحله ای رمز عبور یکبار مصرف (TOTP) مبتنی بر زمان (MFA) را به برنامه خود اضافه کنید.

احراز هویت Firebase با پلتفرم هویت به شما امکان می دهد از TOTP به عنوان یک عامل اضافی برای MFA استفاده کنید. وقتی این ویژگی را فعال می‌کنید، کاربرانی که تلاش می‌کنند به برنامه شما وارد شوند، درخواست TOTP را مشاهده می‌کنند. برای تولید آن، آنها باید از یک برنامه احراز هویت که قادر به تولید کدهای معتبر TOTP باشد، مانند Google Authenticator استفاده کنند.

قبل از اینکه شروع کنی

  1. حداقل یک ارائه دهنده را فعال کنید که از MFA پشتیبانی می کند. توجه داشته باشید که همه ارائه دهندگان به جز MFA زیر پشتیبانی می کنند:

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

  3. اگر قبلاً این کار را نکرده‌اید، Firebase JavaScript SDK را نصب کنید.

    TOTP MFA فقط در Web SDK مدولار، نسخه‌های 9.19.1 و بالاتر پشتیبانی می‌شود.

TOTP MFA را فعال کنید

برای فعال کردن TOTP به عنوان عامل دوم، از Admin SDK استفاده کنید یا با پیکربندی پروژه نقطه پایانی REST تماس بگیرید.

برای استفاده از Admin SDK، موارد زیر را انجام دهید:

  1. اگر قبلاً این کار را انجام نداده‌اید، Firebase Admin Node.js SDK را نصب کنید.

    TOTP MFA فقط در Firebase Admin Node.js SDK نسخه های 11.6.0 و بالاتر پشتیبانی می شود.

  2. موارد زیر را اجرا کنید:

    import { getAuth } from 'firebase-admin/auth';
    
    getAuth().projectConfigManager().updateProjectConfig(
    {
          multiFactorConfig: {
              providerConfigs: [{
                  state: "ENABLED",
                  totpProviderConfig: {
                      adjacentIntervals: {
                          NUM_ADJ_INTERVALS
                      },
                  }
              }]
          }
    })
    

    موارد زیر را جایگزین کنید:

    • NUM_ADJ_INTERVALS : تعداد فواصل پنجره زمانی مجاور که از آن ها TOTP ها را می پذیرند، از صفر تا ده. پیش فرض پنج است.

      TOTP ها با اطمینان از اینکه وقتی دو طرف (اثبات کننده و تایید کننده) OTP را در یک پنجره زمانی (معمولاً 30 ثانیه) تولید می کنند، رمز عبور یکسانی تولید می کنند، کار می کنند. با این حال، برای تطبیق تغییر ساعت بین طرفین و زمان پاسخ انسان، می‌توانید سرویس TOTP را طوری پیکربندی کنید که TOTPها را از پنجره‌های مجاور نیز بپذیرد.

برای فعال کردن TOTP MFA با استفاده از REST API، موارد زیر را اجرا کنید:

curl -X PATCH "https://identitytoolkit.googleapis.com/admin/v2/projects/PROJECT_ID/config?updateMask=mfa" \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    -H "Content-Type: application/json" \
    -H "X-Goog-User-Project: PROJECT_ID" \
    -d \
    '{
        "mfa": {
          "providerConfigs": [{
            "state": "ENABLED",
            "totpProviderConfig": {
              "adjacentIntervals": "NUM_ADJ_INTERVALS"
            }
          }]
       }
    }'

موارد زیر را جایگزین کنید:

  • PROJECT_ID : شناسه پروژه.
  • NUM_ADJ_INTERVALS : تعداد فواصل پنجره زمانی، از صفر تا ده. پیش فرض پنج است.

    TOTP ها با اطمینان از اینکه وقتی دو طرف (اثبات کننده و تایید کننده) OTP را در یک پنجره زمانی (معمولاً 30 ثانیه) تولید می کنند، رمز عبور یکسانی تولید می کنند، کار می کنند. با این حال، برای تطبیق تغییر ساعت بین طرفین و زمان پاسخ انسان، می‌توانید سرویس TOTP را طوری پیکربندی کنید که TOTPها را از پنجره‌های مجاور نیز بپذیرد.

الگوی ثبت نام را انتخاب کنید

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

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

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

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

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

ثبت نام کاربران در TOTP MFA

پس از اینکه TOTP MFA را به عنوان عامل دوم برای برنامه خود فعال کردید، منطق سمت مشتری را برای ثبت نام کاربران در TOTP MFA پیاده سازی کنید:

  1. وارد کردن کلاس ها و توابع MFA مورد نیاز:

    import {
      multiFactor,
      TotpMultiFactorGenerator,
      TotpSecret,
      getAuth,
    } from "firebase/auth";
    
  2. احراز هویت مجدد کاربر

  3. یک راز TOTP برای کاربر احراز هویت شده ایجاد کنید:

    // Generate a TOTP secret.
    const multiFactorSession = await multiFactor(currentUser).getSession();
    const totpSecret = await TotpMultiFactorGenerator.generateSecret(
      multiFactorSession
    );
    
  4. راز را به کاربر نمایش دهید و از او بخواهید آن را در برنامه احراز هویت خود وارد کند.

    با بسیاری از برنامه‌های احراز هویت، کاربران می‌توانند با اسکن یک کد QR که نشان‌دهنده یک URI کلید سازگار با Google Authenticator است، اسرار جدید TOTP را به سرعت اضافه کنند. برای تولید یک کد QR برای این منظور، URI را با generateQrCodeUrl() ایجاد کنید و سپس با استفاده از کتابخانه کد QR انتخابی خود، آن را رمزگذاری کنید. مثلا:

    const totpUri = totpSecret.generateQrCodeUrl(
        currentUser.email,
        "Your App's Name"
    );
    await QRExampleLib.toCanvas(totpUri, qrElement);
    

    صرف نظر از اینکه کد QR را نمایش می دهید، همیشه کلید مخفی را برای پشتیبانی از برنامه های احراز هویت که نمی توانند کدهای QR را بخوانند نمایش دهید:

    // Also display this key:
    const secret = totpSecret.secretKey;
    

    پس از اینکه کاربر راز خود را به برنامه احراز هویت خود اضافه کرد، شروع به تولید TOTP می کند.

  5. از کاربر بخواهید تا TOTP نمایش داده شده در برنامه احراز هویت خود را تایپ کند و از آن برای نهایی کردن ثبت نام MFA استفاده کند:

    // Ask the user for a verification code from the authenticator app.
    const verificationCode = // Code from user input.
    
    // Finalize the enrollment.
    const multiFactorAssertion = TotpMultiFactorGenerator.assertionForEnrollment(
      totpSecret,
      verificationCode
    );
    await multiFactor(currentUser).enroll(multiFactorAssertion, mfaDisplayName);
    

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

برای ورود کاربران با TOTP MFA از کد زیر استفاده کنید:

  1. وارد کردن کلاس ها و توابع MFA مورد نیاز:

    import {
        getAuth,
        getMultiFactorResolver,
        TotpMultiFactorGenerator,
    } from "firebase/auth";
    
  2. همانطور که اگر از MFA استفاده نمی‌کردید، یکی از روش‌های signInWith - را فراخوانی کنید. (به عنوان مثال، signInWithEmailAndPassword() .) اگر روش خطای auth/multi-factor-auth-required را نشان داد، جریان MFA برنامه خود را شروع کنید.

    try {
        const userCredential = await signInWithEmailAndPassword(
            getAuth(),
            email,
            password
        );
        // If the user is not enrolled with a second factor and provided valid
        // credentials, sign-in succeeds.
    
        // (If your app requires MFA, this could be considered an error
        // condition, which you would resolve by forcing the user to enroll a
        // second factor.)
    
        // ...
    } catch (error) {
        switch (error.code) {
            case "auth/multi-factor-auth-required":
                // Initiate your second factor sign-in flow. (See next step.)
                // ...
                break;
            case ...:  // Handle other errors, such as wrong passwords.
                break;
        }
    }
    
  3. جریان MFA برنامه شما ابتدا باید از کاربر بخواهد عامل دومی را که می‌خواهد استفاده کند انتخاب کند. با بررسی ویژگی hints یک نمونه MultiFactorResolver می‌توانید فهرستی از فاکتورهای دوم پشتیبانی شده را دریافت کنید:

    const mfaResolver = getMultiFactorResolver(getAuth(), error);
    const enrolledFactors = mfaResolver.hints.map(info => info.displayName);
    
  4. اگر کاربر استفاده از TOTP را انتخاب کرد، از او بخواهید تا TOTP نمایش داده شده در برنامه احراز هویت خود را تایپ کند و از آن برای ورود به سیستم استفاده کند:

    switch (mfaResolver.hints[selectedIndex].factorId) {
        case TotpMultiFactorGenerator.FACTOR_ID:
            const otpFromAuthenticator = // OTP typed by the user.
            const multiFactorAssertion =
                TotpMultiFactorGenerator.assertionForSignIn(
                    mfaResolver.hints[selectedIndex].uid,
                    otpFromAuthenticator
                );
            try {
                const userCredential = await mfaResolver.resolveSignIn(
                    multiFactorAssertion
                );
                // Successfully signed in!
            } catch (error) {
                // Invalid or expired OTP.
            }
            break;
        case PhoneMultiFactorGenerator.FACTOR_ID:
            // Handle SMS second factor.
            break;
        default:
            // Unsupported second factor?
            break;
    }
    

لغو ثبت نام از TOTP MFA

این بخش نحوه رسیدگی به یک کاربر در حال لغو ثبت نام از TOTP MFA را شرح می دهد.

اگر کاربر برای چندین گزینه MFA ثبت نام کرده باشد، و اگر از آخرین گزینه فعال شده خارج شود، یک auth/user-token-expired دریافت می کند و از سیستم خارج می شود. کاربر باید دوباره وارد سیستم شود و اعتبار موجود خود را تأیید کند - به عنوان مثال، آدرس ایمیل و رمز عبور.

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

import {
    EmailAuthProvider,
    TotpMultiFactorGenerator,
    getAuth,
    multiFactor,
    reauthenticateWithCredential,
} from "firebase/auth";

try {
    // Unenroll from TOTP MFA.
    await multiFactor(currentUser).unenroll(mfaEnrollmentId);
} catch  (error) {
    if (error.code === 'auth/user-token-expired') {
        // If the user was signed out, re-authenticate them.

        // For example, if they signed in with a password, prompt them to
        // provide it again, then call `reauthenticateWithCredential()` as shown
        // below.

        const credential = EmailAuthProvider.credential(email, password);
        await reauthenticateWithCredential(
            currentUser,
            credential
        );
    }
}

بعدش چی