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

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

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

قبل البدء

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

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

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

    لا تتوافق المصادقة المتعدّدة العوامل (MFA) المستندة إلى كلمة مرور لمرة واحدة مستندة إلى الوقت (TOTP) إلا مع الإصدار 22.1.0 والإصدارات الأحدث من حزمة تطوير البرامج (SDK) لنظام Android.

تفعيل المصادقة المتعدّدة العوامل (MFA) المستندة إلى كلمة مرور لمرة واحدة مستندة إلى الوقت (TOTP)

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

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

  1. ثبِّت حزمة تطوير البرامج (SDK) للمشرف في Firebase لنظام Node.js إذا لم يسبق لك إجراء ذلك.

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

لتفعيل المصادقة المتعدّدة العوامل (MFA) المستندة إلى كلمة مرور لمرة واحدة مستندة إلى الوقت (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) من الفترات الزمنية المجاورة أيضًا.

اختيار نمط تسجيل

يمكنك اختيار ما إذا كان تطبيقك يتطلّب المصادقة المتعدّدة العوامل (MFA)، وكيفية تسجيل المستخدمين ومتى يتم ذلك. في ما يلي بعض الأنماط الشائعة:

  • تسجيل العامل الثاني للمستخدم كجزء من عملية التسجيل. استخدِم هذه الطريقة إذا كان تطبيقك يتطلّب المصادقة المتعدّدة العوامل (MFA) لجميع المستخدمين.

  • توفير خيار قابل للتخطّي لتسجيل عامل ثانٍ أثناء التسجيل. إذا كنت تريد تشجيع المصادقة المتعدّدة العوامل (MFA) في تطبيقك ولكن لا تريد فرضها، يمكنك استخدام هذا النهج.

  • توفير إمكانية إضافة عامل ثانٍ من صفحة إدارة الحساب أو الملف الشخصي للمستخدم، بدلاً من شاشة الاشتراك. يقلّل ذلك من المشاكل أثناء عملية التسجيل، مع إتاحة المصادقة المتعدّدة العوامل (MFA) للمستخدمين الذين يهتمون بالأمان.

  • فرض إضافة عامل ثانٍ تدريجيًا عندما يريد المستخدم الوصول إلى ميزات تتطلّب مستوى أمان أعلى.

تسجيل المستخدمين في المصادقة المتعدّدة العوامل (MFA) المستندة إلى كلمة مرور لمرة واحدة مستندة إلى الوقت (TOTP)

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

  1. أعِد مصادقة المستخدم.

  2. أنشئ سرًا لكلمة مرور لمرة واحدة مستندة إلى الوقت (TOTP) للمستخدم الذي تمّت مصادقته:

    // Generate a TOTP secret.
    Firebase.auth.currentUser.multiFactor.session
        .addOnSuccessListener { multiFactorSession ->
            TotpMultiFactorGenerator.generateSecret(multiFactorSession)
                .addOnSuccessListener { totpSecret ->
                    // Display the secret to the user and prompt them to
                    // enter it into their authenticator app. (See the next
                    // step.)
                }
        }
    
  3. اعرض السر للمستخدم واطلب منه إدخاله في تطبيق المصادقة:

    // Display this key:
    val secret = totpSecret.sharedSecretKey
    

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

    val qrCodeUri = totpSecret.generateQrCodeUrl(
        currentUser.email ?: "default account",
        "Your App Name")
    totpSecret.openInOtpApp(qrCodeUri)
    

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

  4. اطلب من المستخدم كتابة كلمة المرور لمرة واحدة مستندة إلى الوقت (TOTP) التي يعرضها تطبيق المصادقة واستخدامها لإنهاء عملية التسجيل في المصادقة المتعدّدة العوامل (MFA):

    // Ask the user for a verification code from the authenticator app.
    val verificationCode = // Code from user input.
    
    // Finalize the enrollment.
    val multiFactorAssertion = TotpMultiFactorGenerator
        .getAssertionForEnrollment(totpSecret, verificationCode)
    Firebase.auth.currentUser.multiFactor.enroll(multiFactorAssertion, "TOTP")
        .addOnSuccessListener {
            // Enrollment complete.
        }
    

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

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

  1. استدعِ إحدى طرق signInWith- كما لو كنت لا تستخدم المصادقة المتعدّدة العوامل (MFA). (على سبيل المثال، signInWithEmailAndPassword().) إذا عرضت الطريقة FirebaseAuthMultiFactorException، ابدأ مسار المصادقة المتعدّدة العوامل (MFA) في تطبيقك.

    Firebase.auth.signInWithEmailAndPassword(email, password)
        .addOnSuccessListener { result ->
            // 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.)
    
            // ...
        }
        .addOnFailureListener { exception ->
            when (exception) {
                is FirebaseAuthMultiFactorException -> {
                    // Initiate your second factor sign-in flow. (See next step.)
                    // ...
                }
            }
        }
    
  2. يجب أن يطلب مسار المصادقة المتعدّدة العوامل (MFA) في تطبيقك أولاً من المستخدم اختيار العامل الثاني الذي يريد استخدامه. يمكنك الحصول على قائمة بالعوامل الثانية المتاحة من خلال فحص السمة hints في مثيل MultiFactorResolver:

    val enrolledFactors = exception.resolver.hints.map { it.displayName }
    
  3. إذا اختار المستخدم استخدام كلمة مرور لمرة واحدة مستندة إلى الوقت (TOTP)، اطلب منه كتابة كلمة المرور لمرة واحدة مستندة إلى الوقت (TOTP) المعروضة في تطبيق المصادقة واستخدامها لتسجيل الدخول:

    when (exception.resolver.hints[selectedIndex].factorId) {
        TotpMultiFactorGenerator.FACTOR_ID -> {
            val otpFromAuthenticator = // OTP typed by the user.
            val assertion = TotpMultiFactorGenerator.getAssertionForSignIn(
                exception.resolver.hints[selectedIndex].uid,
                otpFromAuthenticator
            )
            exception.resolver.resolveSignIn(assertion)
                .addOnSuccessListener { result ->
                    // Successfully signed in!
                }
                .addOnFailureListener { resolveError ->
                    // Invalid or expired OTP.
                }
        }
        PhoneMultiFactorGenerator.FACTOR_ID -> {
            // Handle SMS second factor.
        }
    }
    

إلغاء التسجيل في المصادقة المتعدّدة العوامل (MFA) المستندة إلى كلمة مرور لمرة واحدة مستندة إلى الوقت (TOTP)

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

إذا كان المستخدم قد اشترك في خيارات متعدّدة للمصادقة المتعدّدة العوامل (MFA)، وإذا ألغى تسجيله في الخيار الذي تم تفعيله مؤخرًا، سيتلقّى الرمز auth/user-token-expired وسيتم تسجيل خروجه. على المستخدم تسجيل الدخول مرة أخرى والتحقّق من بيانات الاعتماد الحالية، مثل عنوان البريد الإلكتروني وكلمة المرور.

لإلغاء تسجيل المستخدم والتعامل مع الخطأ وبدء عملية إعادة المصادقة، استخدِم الرمز التالي:

Firebase.auth.currentUser.multiFactor.unenroll(mfaEnrollmentId)
    .addOnSuccessListener {
        // Second factor unenrolled.
    }
    .addOnFailureListener { exception ->
        when (exception) {
            is FirebaseAuthInvalidUserException -> {
                // Second factor unenrolled. 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.
                val credential = EmailAuthProvider.getCredential(email, password)
                currentUser.reauthenticate(credential)
                    .addOnSuccessListener { 
                        // Success!
                    }
                    .addOnFailureListener { 
                        // Bad email address and password combination.
                    }
            }
        }
    }

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