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

إذا كنت قد أجريت ترقية إلى "مصادقة Firebase" باستخدام Identity Platform، يمكنك إضافة المصادقة المتعدّدة العوامل عبر رسائل SMS إلى تطبيق Flutter.

تزيد المصادقة المتعدّدة العوامل (MFA) من أمان تطبيقك. وفي حين أنّ المهاجمين غالبًا ما يخترقون كلمات المرور والحسابات على وسائل التواصل الاجتماعي، يكون اعتراض رسالة نصية أكثر صعوبة.

قبل البدء

  1. فعِّل مزودًا واحدًا على الأقل يتيح المصادقة المتعدّدة العوامل. يتيح كل مزود المصادقة المتعدّدة العوامل، باستثناء المصادقة عبر الهاتف والمصادقة المجهولة وApple Game Center.

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

تفعيل المصادقة المتعدّدة العوامل

  1. في وحدة تحكّم Firebase، انتقِل إلى الأمان > المصادقة.

  2. في علامة التبويب طريقة تسجيل الدخول ، ضِمن قسم الإعدادات المتقدّمة ، فعِّل المصادقة المتعدّدة العوامل عبر رسائل SMS.

    عليك أيضًا إدخال أرقام الهواتف التي ستختبر تطبيقك بها. على الرغم من أنّ تسجيل أرقام هواتف الاختبار هو إجراء اختياري، ننصحك بشدة بإجرائه لتجنُّب تقييد المعدّل أثناء التطوير.

  3. إذا لم يسبق لك إجراء ذلك، عليك منح الإذن لنطاق تطبيقك:

    1. في وحدة تحكّم Firebase، انتقِل إلى علامة التبويب الأمان > المصادقة > الإعدادات.

    2. في قسم النطاقات المصرّح بها ، انقر على إضافة نطاق، وأضِف نطاقك.

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

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

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

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

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

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

تسجيل عامل ثانٍ

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

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

  2. اطلب من المستخدم إدخال رقم هاتفه.

  3. احصل على جلسة متعدّدة العوامل للمستخدم:

    final multiFactorSession = await user.multiFactor.getSession();
    
  4. أثبِت ملكية رقم الهاتف باستخدام جلسة متعدّدة العوامل وعمليات معاودة الاتصال:

    await FirebaseAuth.instance.verifyPhoneNumber(
      multiFactorSession: multiFactorSession,
      phoneNumber: phoneNumber,
      verificationCompleted: (_) {},
      verificationFailed: (_) {},
      codeSent: (String verificationId, int? resendToken) async {
        // The SMS verification code has been sent to the provided phone number.
        // ...
      },
      codeAutoRetrievalTimeout: (_) {},
    );
    
  5. بعد إرسال رمز SMS، اطلب من المستخدم تأكيد الرمز:

    final credential = PhoneAuthProvider.credential(
      verificationId: verificationId,
      smsCode: smsCode,
    );
    
  6. أكمِل عملية التسجيل:

    await user.multiFactor.enroll(
      PhoneMultiFactorGenerator.getAssertion(
        credential,
      ),
    );
    

يعرض الرمز البرمجي أدناه مثالاً كاملاً على تسجيل عامل ثانٍ:

  final session = await user.multiFactor.getSession();
  final auth = FirebaseAuth.instance;
  await auth.verifyPhoneNumber(
    multiFactorSession: session,
    phoneNumber: phoneController.text,
    verificationCompleted: (_) {},
    verificationFailed: (_) {},
    codeSent: (String verificationId, int? resendToken) async {
      // See `firebase_auth` example app for a method of retrieving user's sms code:
      // https://github.com/firebase/flutterfire/blob/main/packages/firebase_auth/firebase_auth/example/lib/auth.dart#L591
      final smsCode = await getSmsCodeFromUser(context);

      if (smsCode != null) {
        // Create a PhoneAuthCredential with the code
        final credential = PhoneAuthProvider.credential(
          verificationId: verificationId,
          smsCode: smsCode,
        );

        try {
          await user.multiFactor.enroll(
            PhoneMultiFactorGenerator.getAssertion(
              credential,
            ),
          );
        } on FirebaseAuthException catch (e) {
          print(e.message);
        }
      }
    },
    codeAutoRetrievalTimeout: (_) {},
  );

تهانينا! لقد سجّلت بنجاح عامل مصادقة ثانٍ لمستخدم.

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

لتسجيل دخول مستخدم باستخدام ميزة "التحقّق بخطوتين" عبر رسائل SMS:

  1. سجِّل دخول المستخدم باستخدام العامل الأول، ثم رصد الاستثناء FirebaseAuthMultiFactorException. يحتوي هذا الخطأ على أداة حلّ يمكنك استخدامها للحصول على العوامل الثانية المسجّلة للمستخدم. ويحتوي أيضًا على جلسة أساسية تثبت أنّ المستخدم قد نجح في المصادقة باستخدام العامل الأول.

    على سبيل المثال، إذا كان العامل الأول للمستخدم هو عنوان بريد إلكتروني وكلمة مرور:

    try {
      await _auth.signInWithEmailAndPassword(
          email: emailController.text,
          password: passwordController.text,
      );
      // User is not enrolled with a second factor and is successfully
      // signed in.
      // ...
    } on FirebaseAuthMultiFactorException catch (e) {
      // The user is a multi-factor user. Second factor challenge is required
      final resolver = e.resolver
      // ...
    }
    
  2. إذا كان لدى المستخدم عوامل ثانوية متعددة مسجّلة، اطلب منه اختيار العامل الذي يريد استخدامه:

    final session = e.resolver.session;
    
    final hint = e.resolver.hints[selectedHint];
    
  3. أرسِل رسالة تأكيد إلى هاتف المستخدم تتضمّن التلميح والجلسة المتعدّدة العوامل:

    await FirebaseAuth.instance.verifyPhoneNumber(
      multiFactorSession: session,
      multiFactorInfo: hint,
      verificationCompleted: (_) {},
      verificationFailed: (_) {},
      codeSent: (String verificationId, int? resendToken) async {
        // ...
      },
      codeAutoRetrievalTimeout: (_) {},
    );
    
  4. استخدِم resolver.resolveSignIn() لإكمال المصادقة الثانوية:

    final smsCode = await getSmsCodeFromUser(context);
    if (smsCode != null) {
      // Create a PhoneAuthCredential with the code
      final credential = PhoneAuthProvider.credential(
        verificationId: verificationId,
        smsCode: smsCode,
      );
    
      try {
        await e.resolver.resolveSignIn(
          PhoneMultiFactorGenerator.getAssertion(credential)
        );
      } on FirebaseAuthException catch (e) {
        print(e.message);
      }
    }
    

يعرض الرمز البرمجي أدناه مثالاً كاملاً على تسجيل دخول مستخدم متعدّد العوامل:

try {
  await _auth.signInWithEmailAndPassword(
    email: emailController.text,
    password: passwordController.text,
  );
} on FirebaseAuthMultiFactorException catch (e) {
  setState(() {
    error = '${e.message}';
  });
  final firstHint = e.resolver.hints.first;
  if (firstHint is! PhoneMultiFactorInfo) {
    return;
  }
  await FirebaseAuth.instance.verifyPhoneNumber(
    multiFactorSession: e.resolver.session,
    multiFactorInfo: firstHint,
    verificationCompleted: (_) {},
    verificationFailed: (_) {},
    codeSent: (String verificationId, int? resendToken) async {
      // See `firebase_auth` example app for a method of retrieving user's sms code:
      // https://github.com/firebase/flutterfire/blob/main/packages/firebase_auth/firebase_auth/example/lib/auth.dart#L591
      final smsCode = await getSmsCodeFromUser(context);

      if (smsCode != null) {
        // Create a PhoneAuthCredential with the code
        final credential = PhoneAuthProvider.credential(
          verificationId: verificationId,
          smsCode: smsCode,
        );

        try {
          await e.resolver.resolveSignIn(
            PhoneMultiFactorGenerator.getAssertion(
              credential,
            ),
          );
        } on FirebaseAuthException catch (e) {
          print(e.message);
        }
      }
    },
    codeAutoRetrievalTimeout: (_) {},
  );
} catch (e) {
  ...
}

تهانينا! لقد سجّلت دخول مستخدم بنجاح باستخدام المصادقة المتعدّدة العوامل.

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