إضافة المصادقة المتعدّدة العوامل (TOTP) إلى تطبيق الويب

إذا كنت قد أجريت ترقية إلى Firebase Authentication with Identity Platform، يمكنك إضافة المصادقة المتعدّدة العوامل (MFA) المستندة إلى كلمة مرور صالحة لمرة واحدة (TOTP) إلى تطبيقك.

تتيح لك Firebase Authentication with Identity Platform استخدام كلمة مرور لمرة واحدة مستندة إلى الوقت (TOTP) كعامل إضافي للمصادقة المتعدّدة العوامل. عند تفعيل هذه الميزة، ستظهر للمستخدمين الذين يحاولون تسجيل الدخول إلى تطبيقك رسالة تطلب منهم إدخال رمز TOTP. لإنشاء هذا الرمز، يجب استخدام تطبيق مصادقة يمكنه إنشاء رموز TOTP صالحة، مثل Google Authenticator.

قبل البدء

  1. فعِّل موفّرًا واحدًا على الأقل يتيح استخدام المصادقة المتعدّدة العوامل. يُرجى العلم أنّ جميع مقدّمي الخدمة باستثناء ما يلي يتيحون المصادقة المتعدّدة العوامل:

    • مصادقة الهاتف
    • المصادقة بدون تحديد الهوية
    • رموز المصادقة المخصّصة
    • ‫Apple Game Center
  2. تأكَّد من أنّ تطبيقك يتحقّق من عناوين البريد الإلكتروني للمستخدمين. تتطلّب المصادقة المتعددة العوامل تأكيد عنوان البريد الإلكتروني. يمنع ذلك الجهات الضارة من التسجيل في إحدى الخدمات باستخدام عنوان بريد إلكتروني لا تملكه، ثم حظر المالك الفعلي لعنوان البريد الإلكتروني من خلال إضافة عامل مصادقة ثانٍ.

  3. إذا لم يسبق لك إجراء ذلك، ثبِّت حزمة تطوير البرامج (SDK) لخدمة Firebase JavaScript.

    لا تتوفّر المصادقة المتعدّدة العوامل باستخدام كلمة مرور لمرة واحدة مستندة إلى الوقت (TOTP) إلا في حزمة Web SDK النموذجية، الإصدارات 9.19.1 والإصدارات الأحدث.

تفعيل المصادقة المتعددة العوامل المستندة إلى كلمة المرور الصالحة لمرة واحدة

لتفعيل TOTP كعامل ثانٍ، استخدِم Admin SDK أو اتّصِل بنقطة نهاية REST الخاصة بإعدادات المشروع.

لاستخدام Admin SDK، اتّبِع الخطوات التالية:

  1. إذا لم يسبق لك إجراء ذلك، ثبِّت حزمة تطوير البرامج (SDK) لخدمة Firebase Admin Node.js.

    لا تتوافق المصادقة المتعدّدة العوامل باستخدام كلمة مرور لمرة واحدة مستندة إلى الوقت إلا مع الإصدار 11.6.0 والإصدارات الأحدث من حزمة تطوير البرامج (SDK) الخاصة بـ Node.js في "مدير SDK في Firebase".

  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 من الفترات الزمنية المجاورة أيضًا.

لتفعيل المصادقة المتعددة العوامل المستندة إلى كلمة المرور الصالحة لمرة واحدة باستخدام واجهة 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)

بعد تفعيل المصادقة المتعدّدة العوامل المستندة إلى كلمة المرور الصالحة لمرة واحدة (TOTP) كعامل ثانٍ لتطبيقك، عليك تنفيذ منطق من جهة العميل لتسجيل المستخدمين في المصادقة المتعدّدة العوامل المستندة إلى كلمة المرور الصالحة لمرة واحدة (TOTP):

  1. استورِد فئات ووظائف المصادقة المتعددة العوامل المطلوبة:

    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. اعرض السرّ للمستخدم واطلب منه إدخاله في تطبيق المصادقة.

    باستخدام العديد من تطبيقات المصادقة، يمكن للمستخدمين إضافة أسرار TOTP جديدة بسرعة من خلال مسح رمز استجابة سريعة يمثّل معرّف موارد منتظم (URI) لمفتاح متوافق مع Google Authenticator. لإنشاء رمز استجابة سريعة لهذا الغرض، أنشئ معرّف الموارد المنتظم (URI) باستخدام generateQrCodeUrl()، ثم ارمزه باستخدام مكتبة رموز الاستجابة السريعة التي تختارها. على سبيل المثال:

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

    بغض النظر عمّا إذا كنت تعرض رمز استجابة سريعة، احرص دائمًا على عرض المفتاح السري لدعم تطبيقات المصادقة التي لا يمكنها قراءة رموز الاستجابة السريعة:

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

    بعد أن يضيف المستخدم الرمز السري إلى تطبيق المصادقة، سيبدأ التطبيق في إنشاء رموز TOTP.

  5. اطلب من المستخدم كتابة رمز TOTP المعروض على تطبيق المصادقة واستخدامه لإكمال عملية التسجيل في ميزة "المصادقة المتعددة العوامل":

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

تسجيل دخول المستخدمين باستخدام عامل ثانٍ

لتسجيل دخول المستخدمين باستخدام المصادقة المتعددة العوامل المستندة إلى كلمة المرور الصالحة لمرة واحدة، استخدِم الرمز التالي:

  1. استورِد فئات ووظائف المصادقة المتعددة العوامل المطلوبة:

    import {
        getAuth,
        getMultiFactorResolver,
        TotpMultiFactorGenerator,
    } from "firebase/auth";
    
  2. اتّصِل بإحدى طرق signInWith كما لو كنت لا تستخدم المصادقة المتعددة العوامل. (على سبيل المثال، signInWithEmailAndPassword().) إذا عرضت الطريقة الخطأ auth/multi-factor-auth-required، ابدأ مسار المصادقة المتعدّدة العوامل في تطبيقك.

    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. يجب أن يطلب مسار المصادقة المتعدّدة العوامل في تطبيقك من المستخدم أولاً اختيار العامل الثاني الذي يريد استخدامه. يمكنك الحصول على قائمة بالعوامل الثانوية المتوافقة من خلال فحص السمة 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;
    }
    

إلغاء التسجيل في المصادقة المتعدّدة العوامل باستخدام كلمة مرور لمرة واحدة مستندة إلى الوقت

يوضّح هذا القسم كيفية التعامل مع إلغاء المستخدم لتسجيله في المصادقة المتعدّدة العوامل المستندة إلى كلمة المرور الصالحة لمرة واحدة.

إذا اشترك مستخدم في خيارات متعددة للمصادقة المتعددة العوامل، وألغى الاشتراك في الخيار الذي تم تفعيله مؤخرًا، سيتلقّى رسالة 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
        );
    }
}

الخطوات التالية