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

إذا تمت الترقية إلى مصادقة Firebase باستخدام "نظام أساسي للهوية"، يمكنك إضافة كلمة مرور صالحة لمرة واحدة مصادقة متعدّدة العوامل (MFA) على تطبيقك باستخدام TOTP

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

قبل البدء

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

    • المصادقة عبر الهاتف
    • مصادقة مجهولة
    • الرموز المميّزة المخصّصة للمصادقة
    • مركز ألعاب Apple
  2. تأكَّد من أنّ تطبيقك يتحقّق من عناوين البريد الإلكتروني للمستخدمين. تتطلب المواقع المصممة بغرض الإعلانات (MFA) عنوان بريد إلكتروني التحقق. يؤدي هذا الإجراء إلى منع الجهات الضارّة من التسجيل في إحدى الخدمات. بعنوان بريد إلكتروني لا يملكونه، ثم حجب عناوين البريد الإلكتروني مالك عنوان البريد الإلكتروني بإضافة عامل ثانٍ.

  3. ثبِّت حزمة تطوير البرامج (SDK) بلغة Firebase JavaScript

    لا يتوافق TOTP MFA إلا مع حزمة تطوير البرامج (SDK) المستندة إلى الويب، والإصدارات v9.19.1 و أعلاه.

تفعيل TOTP MFA

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

لاستخدام حزمة SDK للمشرف، يمكنك تنفيذ ما يلي:

  1. ثبِّت حزمة تطوير برامج Node.js لمشرف Firebase

    لا يتوافق TOTP MFA إلّا مع الإصدار 11.6.0 والإصدار 11.6.0 من حزمة تطوير البرامج (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 منها، من صفر إلى عشرة. تشير رسالة الأشكال البيانية الافتراضي هو خمسة.

      يعمل المشتركون في "بنود الخدمة" من خلال ضمان أنّه عندما ينفّذ طرفان (الثابت مدقق في البيانات) ينشئون كلمات المرور لمرة واحدة (OTP) في نفس الفترة الزمنية (عادةً ما تكون 30 ثانية). تنشئ كلمة المرور نفسها. ومع ذلك، لتلائم الساعة بين الأطراف ووقت استجابة الإنسان، يمكنك ضبط TOTP قبول بروتوكولات TOTP أيضًا من النوافذ المجاورة.

لتمكين TOTP MFA باستخدام واجهة برمجة تطبيقات REST، قم بتشغيل ما يلي:

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: عدد الإطار الزمني المسافات، من صفر إلى عشرة. والإعداد الافتراضي هو خمسة.

    يعمل المشتركون في "بنود الخدمة" من خلال ضمان أنّه عندما ينفّذ طرفان (الثابت مدقق في البيانات) ينشئون كلمات المرور لمرة واحدة (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. يعرض المفتاح السري للمستخدم واطلب منه إدخاله في تطبيق المصادقة.

    مع العديد من تطبيقات المصادقة، يمكن للمستخدمين إضافة أسرار 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 المعروض على تطبيق المصادقة الخاص به استخدامه لإنهاء عملية التسجيل في المواقع المصممة بغرض الإعلانات (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. يجب أن يطلب تدفق التطبيقات المصممة بغرض الإعلانات من المستخدم أولاً اختيار العامل الثاني التي يريدون استخدامها. يمكنك الحصول على قائمة بالعوامل الثانية المتوافقة من خلال فحص السمة hints لمثيل MultiFactorResolver:

    const mfaResolver = getMultiFactorResolver(getAuth(), error);
    const enrolledFactors = mfaResolver.hints.map(info => info.displayName);
    
  4. إذا اختار المستخدم استخدام 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
        );
    }
}

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