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

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

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

قبل البدء

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

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

  3. Android: إذا لم يسبق لك ضبط تجزئة SHA-256 لتطبيقك في وحدة تحكّم Firebase، عليك إجراء ذلك. اطّلِع على مصادقة العميل للحصول على معلومات عن العثور على تجزئة SHA-256 لتطبيقك.

  4. نظام التشغيل iOS: في Xcode، فعِّل الإشعارات الفورية لمشروعك وتأكَّد من أنّه تم ضبط مفتاح مصادقة APNs باستخدام خدمة المراسلة عبر السحابة الإلكترونية من Firebase (FCM). بالإضافة إلى ذلك، عليك تفعيل أوضاع الخلفية للإشعارات عن بُعد. للاطّلاع على شرح مفصّل لهذه الخطوة، اطّلِع على مستندات Firebase iOS Phone Auth.

  5. الموقع الإلكتروني: تأكَّد من إضافة نطاق تطبيقاتك في وحدة تحكّم Firebase، ضمن نطاقات إعادة التوجيه باستخدام بروتوكول OAuth.

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

  1. افتح صفحة المصادقة > طريقة تسجيل الدخول في "وحدة تحكّم Firebase".

  2. في قسم الإعدادات المتقدّمة، فعِّل المصادقة المتعدّدة العوامل عبر الرسائل القصيرة.

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

  3. إذا لم يسبق لك تفويض نطاق تطبيقك، أضِفه إلى قائمة المسموح بهم في صفحة المصادقة > الإعدادات في وحدة تحكّم Firebase.

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

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

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

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

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

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

تسجيل عامل مصادقة ثانٍ

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

  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. بعد إرسال رمز الرسائل القصيرة، اطلب من المستخدم التحقّق من الرمز:

    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: (_) {},
  );

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

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

لتسجيل دخول مستخدم باستخدام المصادقة الثنائية عبر الرسائل القصيرة:

  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) {
  ...
}

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

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