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

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

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

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

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

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

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

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

فعال کردن TOTP MFA

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

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

  1. اگر قبلاً این کار را نکرده‌اید، کیت توسعه نرم‌افزار (SDK) مربوط به Firebase Admin Node.js را نصب کنید.

    TOTP MFA فقط در نسخه‌های ۱۱.۶.۰ و بالاتر از کیت توسعه نرم‌افزار Firebase Admin Node.js پشتیبانی می‌شود.

  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. یکی از متدهای signInWith - را همانطور که اگر از MFA استفاده نمی‌کردید، فراخوانی می‌کردید، فراخوانی کنید. (برای مثال، 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
        );
    }
}

قدم بعدی چیست؟