المصادقة مع Firebase باستخدام "روابط البريد الإلكتروني"

يمكنك استخدام Firebase Authentication لتسجيل دخول مستخدم من خلال إرسال رسالة إلكترونية إليه تحتوي على رابط يمكنه النقر عليه لتسجيل الدخول. وخلال هذه العملية، يتم أيضًا إثبات ملكية عنوان البريد الإلكتروني للمستخدم.

هناك العديد من المزايا لتسجيل الدخول باستخدام عنوان البريد الإلكتروني:

  • سهولة الاشتراك وتسجيل الدخول
  • تقليل خطر إعادة استخدام كلمة المرور في جميع التطبيقات، ما قد يهدّد أمان كلمات المرور التي تم اختيارها بعناية
  • إمكانية مصادقة مستخدم مع التحقق أيضًا من أنّه هو المالك الشرعي لعنوان بريد إلكتروني
  • يحتاج المستخدم إلى حساب بريد إلكتروني يمكن الوصول إليه فقط لتسجيل الدخول. ولا يُشترط امتلاك رقم هاتف أو حساب على وسائل التواصل الاجتماعي.
  • يمكن للمستخدم تسجيل الدخول بأمان بدون الحاجة إلى تقديم (أو تذكُّر) كلمة مرور، ما قد يكون صعبًا على جهاز جوّال.
  • يمكن ترقية مستخدم حالي سجّل الدخول سابقًا باستخدام معرّف بريد إلكتروني (بكلمة مرور أو مستخدم مُدرَج في مجموعة متعدّدة المؤسسات) ليتمكن من تسجيل الدخول باستخدام البريد الإلكتروني فقط. على سبيل المثال، إذا نسى أحد المستخدمين كلمة مروره، سيظل بإمكانه تسجيل الدخول بدون الحاجة إلى إعادة ضبط كلمة المرور.

قبل البدء

  1. اتّبِع الخطوات الواردة في دليل البدء إذا لم يسبق لك ذلك.

  2. فعِّل ميزة "تسجيل الدخول باستخدام رابط البريد الإلكتروني" لمشروعك على Firebase.

    لتسجيل دخول المستخدمين من خلال رابط البريد الإلكتروني، عليك أولاً تفعيل مقدّم خدمة البريد الإلكتروني وطريقة تسجيل الدخول باستخدام رابط البريد الإلكتروني لمشروعك على Firebase:

    1. في وحدة تحكُّم Firebase، افتح قسم Auth.
    2. في علامة التبويب طريقة تسجيل الدخول، فعِّل موفِّر البريد الإلكتروني/كلمة المرور. يُرجى العلم أنّه يجب تفعيل تسجيل الدخول باستخدام عنوان البريد الإلكتروني/كلمة المرور لاستخدام ميزة تسجيل الدخول باستخدام رابط البريد الإلكتروني.
    3. في القسم نفسه، فعِّل طريقة تسجيل الدخول رابط البريد الإلكتروني (تسجيل الدخول بدون كلمة مرور).
    4. انقر على حفظ.

لبدء عملية المصادقة، عليك عرض واجهة تطلب من المستخدم تقديم عنوان بريده الإلكتروني، ثم الاتصال برقم sendSignInLinkToEmail() لطلب أن ترسل Firebase رابط المصادقة إلى عنوان البريد الإلكتروني للمستخدم.

  1. أنشئ عنصر ActionCodeSettings الذي يقدّم لـ Firebase تعليمات حول كيفية إنشاء رابط البريد الإلكتروني. اضبط الحقول التالية:

    • url: الرابط لصفحة في التطبيق المطلوب تضمينه وأي حالة إضافية المطلوب تمريرها يجب أن يكون نطاق الرابط متوفرًا في قائمة النطاقات المعتمَدة في وحدة تحكّم Firebase، والتي يمكن العثور عليها من خلال الانتقال إلى علامة التبويب "الإعدادات" (المصادقة -> الإعدادات -> النطاقات المعتمَدة). سيعيد الرابط توجيه العميل إلى عنوان URL هذا إذا لم يكن التطبيق مثبّتًا على جهازه ولم يكن بإمكانه تثبيته.

    • androidPackageName وIOSBundleId: التطبيقات المُستخدَمة عند فتح رابط تسجيل الدخول على جهاز Android أو iOS اطّلِع على مزيد من المعلومات عن كيفية ضبط "الروابط الديناميكية من Firebase" لفتح روابط إجراءات البريد الإلكتروني من خلال التطبيقات المتوافقة مع الأجهزة الجوّالة.

    • handleCodeInApp: اضبطها على true. يجب إكمال عملية تسجيل الدخول دائمًا في التطبيق على عكس الإجراءات الأخرى التي تتم خارج النطاق باستخدام البريد الإلكتروني (مثل إعادة ضبط كلمة المرور وإثبات ملكية البريد الإلكتروني). ويعود السبب في ذلك إلى أنّه من المتوقّع أن يكون المستخدم مسجِّلاً الدخول في نهاية العملية وأن تظل حالة المصادقة محفوظة داخل التطبيق.

    • dynamicLinkDomain: (تم إيقافه نهائيًا، استخدِم linkDomain) عند تحديد عدة نطاقات روابط ديناميكية مخصّصة لمشروع معيّن، حدِّد النطاق الذي ستستخدمه عند فتح الرابط باستخدام تطبيق جوّال محدّد (مثل example.page.link). وإلا، سيتم تحديد النطاق الأول تلقائيًا.

    • linkDomain: نطاق استضافة Firebase المخصّص الاختياري لاستخدامه عند فتح الرابط باستخدام تطبيق جوّال محدّد. يجب ضبط النطاق في "استضافة Firebase" وأن يكون مملوكًا للمشروع. لا يمكن أن يكون هذا النطاق هو نطاق استضافة تلقائي (web.app أو firebaseapp.com). ويحلّ هذا الإعداد محلّ الإعداد dynamicLinkDomain الذي تم إيقافه نهائيًا.

    var acs = ActionCodeSettings(
        // URL you want to redirect back to. The domain (www.example.com) for this
        // URL must be whitelisted in the Firebase Console.
        url: 'https://www.example.com/finishSignUp?cartId=1234',
        // This must be true
        handleCodeInApp: true,
        iOSBundleId: 'com.example.ios',
        androidPackageName: 'com.example.android',
        // installIfNotAvailable
        androidInstallApp: true,
        // minimumVersion
        androidMinimumVersion: '12');
    
  2. اطلب من المستخدم عنوان بريده الإلكتروني.

  3. أرسِل رابط المصادقة إلى عنوان البريد الإلكتروني للمستخدم، واحفظ عنوان البريد الإلكتروني للمستخدم في حال أكمل المستخدم عملية تسجيل الدخول باستخدام البريد الإلكتروني على الجهاز نفسه.

    var emailAuth = 'someemail@domain.com';
    FirebaseAuth.instance.sendSignInLinkToEmail(
            email: emailAuth, actionCodeSettings: acs)
        .catchError((onError) => print('Error sending email verification $onError'))
        .then((value) => print('Successfully sent email verification'));
    });
    

المخاوف المرتبطة بالأمان

لمنع استخدام رابط تسجيل الدخول لتسجيل الدخول بصفتك مستخدمًا غير مقصود أو على جهاز غير مقصود، تتطلّب Firebase Auth تقديم عنوان البريد الإلكتروني للمستخدم عند إكمال عملية تسجيل الدخول. لكي تنجح عملية تسجيل الدخول، يجب أن يتطابق عنوان البريد الإلكتروني هذا مع العنوان الذي تم إرسال رابط تسجيل الدخول إليه في الأصل.

يمكنك تبسيط هذه العملية للمستخدمين الذين يفتحون رابط تسجيل الدخول على الجهاز نفسه الذي طلبوا الرابط منه، وذلك من خلال تخزين عنوان بريدهم الإلكتروني على الجهاز - مثلاً باستخدام SharedPreferences - عند إرسال الرسالة الإلكترونية لتسجيل الدخول. بعد ذلك، استخدِم هذا العنوان لإكمال عملية الدفع. لا تُرسِل عنوان البريد الإلكتروني للمستخدم في مَعلمات عنوان URL لإعادة التوجيه ولا تُعيد استخدامه لأنّه قد يؤدي ذلك إلى تفعيل عمليات إدخال الجلسات.

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

تأكَّد أيضًا من استخدام عنوان URL بتنسيق HTTPS في مرحلة الإنتاج لتجنُّب احتمال اعتراض الرابط من قِبل الخوادم الوسيطة.

إكمال عملية تسجيل الدخول

تم إيقاف ميزة "روابط Firebase الديناميكية" نهائيًا، ويتم الآن استخدام ميزة "استضافة Firebase" لإرسال رابط تسجيل الدخول. اتّبِع الأدلة الخاصة بالإعدادات الخاصة بالمنصة:

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

  1. في معالِج الرابط، تحقَّق مما إذا كان الرابط مخصّصًا لمصادقة رابط البريد الإلكتروني، وإذا كان الأمر كذلك، أكمِل عملية تسجيل الدخول.

    // Confirm the link is a sign-in with email link.
    if (FirebaseAuth.instance.isSignInWithEmailLink(emailLink)) {
      try {
        // The client SDK will parse the code from the link for you.
        final userCredential = await FirebaseAuth.instance
            .signInWithEmailLink(email: emailAuth, emailLink: emailLink);
    
        // You can access the new user via userCredential.user.
        final emailAddress = userCredential.user?.email;
    
        print('Successfully signed in with email link!');
      } catch (error) {
        print('Error signing in with email link.');
      }
    }
    

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

سيكون الفرق في النصف الثاني من العملية:

final authCredential = EmailAuthProvider
    .credentialWithLink(email: emailAuth, emailLink: emailLink.toString());
try {
    await FirebaseAuth.instance.currentUser
        ?.linkWithCredential(authCredential);
} catch (error) {
    print("Error linking emailLink credential.");
}

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

final authCredential = EmailAuthProvider
    .credentialWithLink(email: emailAuth, emailLink: emailLink.toString());
try {
    await FirebaseAuth.instance.currentUser
        ?.reauthenticateWithCredential(authCredential);
} catch (error) {
    print("Error reauthenticating credential.");
}

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

إذا أنشأت مشروعك في 15 أيلول (سبتمبر) 2023 أو بعد هذا التاريخ، سيتم تفعيل الحماية ضد التعداد للبريد الإلكتروني تلقائيًا. تحسِّن هذه الميزة أمان حسابات مستخدمي مشروعك، ولكنها تُوقِف طريقة fetchSignInMethodsForEmail() التي كنا ننصح بها سابقًا لتنفيذ عمليات الربط بالمعرّف أولاً.

على الرغم من أنّه يمكنك إيقاف ميزة "حماية تعداد عناوين البريد الإلكتروني" لمشروعك، ننصحك بعدم إجراء ذلك.

اطّلِع على المستندات حول حماية تعداد عناوين البريد الإلكتروني لمزيد من التفاصيل.

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

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

في تطبيقاتك، يمكنك الحصول على معلومات الملف الشخصي الأساسية للمستخدم من عنصر User. راجِع إدارة المستخدِمين.

في قواعد أمان Firebase Realtime Database وCloud Storage، يمكنك الحصول على معرّف المستخدِم الفريد للمستخدِم الذي سجّل الدخول من المتغيّر auth، واستخدامه لمحاولة التحكّم في البيانات التي يمكن للمستخدِم الوصول إليها.

يمكنك السماح للمستخدمين بتسجيل الدخول إلى تطبيقك باستخدام عدة موفّري مصادقة من خلال ربط بيانات اعتماد موفّر المصادقة) بحساب مستخدمحالٍ.

لتسجيل خروج مستخدم، يُرجى الاتصال على signOut():

await FirebaseAuth.instance.signOut();