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

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

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

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

قبل البدء

انسخ مقتطف الإعداد من وحدة تحكّم Firebase إلى مشروعك على النحو الموضّح في المقالة إضافة Firebase إلى مشروع JavaScript إذا لم يسبق لك إجراء ذلك.

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

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

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

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

    • url: هو الرابط لصفحة معيّنة التي سيتم تضمينها وأي حالة إضافية يجب تمريرها. يجب إضافة نطاق الرابط إلى قائمة "وحدة تحكُّم Firebase" للنطاقات المعتمَدة، والتي يمكن العثور عليها من خلال الانتقال إلى علامة التبويب "طريقة تسجيل الدخول" (المصادقة -> الإعدادات).
    • android وios: التطبيقان المطلوب استخدامهما عند فتح رابط تسجيل الدخول على جهاز Android أو Apple. اطّلع على مزيد من المعلومات عن كيفية ضبط روابط Firebase الديناميكية لفتح روابط إجراءات البريد الإلكتروني عبر التطبيقات للأجهزة الجوّالة.
    • handleCodeInApp: تم ضبطها على "صحيح". يجب أن تكتمل عملية تسجيل الدخول دائمًا في التطبيق، على عكس الإجراءات الأخرى التي تتعلّق بالبريد الإلكتروني خارج النطاق (أي إعادة ضبط كلمة المرور وإثبات ملكية عنوان البريد الإلكتروني). ويرجع ذلك إلى أنّه في نهاية عملية الإعداد، يُتوقّع من المستخدم تسجيل الدخول واستمرار حالة المصادقة داخل التطبيق.
    • dynamicLinkDomain: عند تحديد عدة نطاقات روابط ديناميكية مخصّصة لمشروع ما، عليك تحديد النطاق الذي تريد استخدامه عند فتح الرابط من خلال تطبيق متوافق مع الأجهزة الجوّالة محدّد (مثل example.page.link)، وإلا يتم اختيار النطاق الأول تلقائيًا.

      واجهة برمجة التطبيقات Web modular API

      const actionCodeSettings = {
        // URL you want to redirect back to. The domain (www.example.com) for this
        // URL must be in the authorized domains list in the Firebase Console.
        url: 'https://www.example.com/finishSignUp?cartId=1234',
        // This must be true.
        handleCodeInApp: true,
        iOS: {
          bundleId: 'com.example.ios'
        },
        android: {
          packageName: 'com.example.android',
          installApp: true,
          minimumVersion: '12'
        },
        dynamicLinkDomain: 'example.page.link'
      };

      واجهة برمجة التطبيقات لمساحة الاسم على الويب

      var actionCodeSettings = {
        // URL you want to redirect back to. The domain (www.example.com) for this
        // URL must be in the authorized domains list in the Firebase Console.
        url: 'https://www.example.com/finishSignUp?cartId=1234',
        // This must be true.
        handleCodeInApp: true,
        iOS: {
          bundleId: 'com.example.ios'
        },
        android: {
          packageName: 'com.example.android',
          installApp: true,
          minimumVersion: '12'
        },
        dynamicLinkDomain: 'example.page.link'
      };

    للمزيد من المعلومات حول ActionCodeSettings، يمكنك الرجوع إلى قسم حالة النجاح في إجراءات البريد الإلكتروني.

  2. اطلب من المستخدم إدخال بريده الإلكتروني.

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

    واجهة برمجة التطبيقات Web modular API

    import { getAuth, sendSignInLinkToEmail } from "firebase/auth";
    
    const auth = getAuth();
    sendSignInLinkToEmail(auth, email, actionCodeSettings)
      .then(() => {
        // The link was successfully sent. Inform the user.
        // Save the email locally so you don't need to ask the user for it again
        // if they open the link on the same device.
        window.localStorage.setItem('emailForSignIn', email);
        // ...
      })
      .catch((error) => {
        const errorCode = error.code;
        const errorMessage = error.message;
        // ...
      });

    واجهة برمجة التطبيقات لمساحة الاسم على الويب

    firebase.auth().sendSignInLinkToEmail(email, actionCodeSettings)
      .then(() => {
        // The link was successfully sent. Inform the user.
        // Save the email locally so you don't need to ask the user for it again
        // if they open the link on the same device.
        window.localStorage.setItem('emailForSignIn', email);
        // ...
      })
      .catch((error) => {
        var errorCode = error.code;
        var errorMessage = error.message;
        // ...
      });

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

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

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

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

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

إكمال تسجيل الدخول في صفحة ويب

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

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

واجهة برمجة التطبيقات Web modular API

import { getAuth, isSignInWithEmailLink, signInWithEmailLink } from "firebase/auth";

// Confirm the link is a sign-in with email link.
const auth = getAuth();
if (isSignInWithEmailLink(auth, window.location.href)) {
  // Additional state parameters can also be passed via URL.
  // This can be used to continue the user's intended action before triggering
  // the sign-in operation.
  // Get the email if available. This should be available if the user completes
  // the flow on the same device where they started it.
  let email = window.localStorage.getItem('emailForSignIn');
  if (!email) {
    // User opened the link on a different device. To prevent session fixation
    // attacks, ask the user to provide the associated email again. For example:
    email = window.prompt('Please provide your email for confirmation');
  }
  // The client SDK will parse the code from the link for you.
  signInWithEmailLink(auth, email, window.location.href)
    .then((result) => {
      // Clear email from storage.
      window.localStorage.removeItem('emailForSignIn');
      // You can access the new user by importing getAdditionalUserInfo
      // and calling it with result:
      // getAdditionalUserInfo(result)
      // You can access the user's profile via:
      // getAdditionalUserInfo(result)?.profile
      // You can check if the user is new or existing:
      // getAdditionalUserInfo(result)?.isNewUser
    })
    .catch((error) => {
      // Some error occurred, you can inspect the code: error.code
      // Common errors could be invalid email and invalid or expired OTPs.
    });
}

واجهة برمجة التطبيقات لمساحة الاسم على الويب

// Confirm the link is a sign-in with email link.
if (firebase.auth().isSignInWithEmailLink(window.location.href)) {
  // Additional state parameters can also be passed via URL.
  // This can be used to continue the user's intended action before triggering
  // the sign-in operation.
  // Get the email if available. This should be available if the user completes
  // the flow on the same device where they started it.
  var email = window.localStorage.getItem('emailForSignIn');
  if (!email) {
    // User opened the link on a different device. To prevent session fixation
    // attacks, ask the user to provide the associated email again. For example:
    email = window.prompt('Please provide your email for confirmation');
  }
  // The client SDK will parse the code from the link for you.
  firebase.auth().signInWithEmailLink(email, window.location.href)
    .then((result) => {
      // Clear email from storage.
      window.localStorage.removeItem('emailForSignIn');
      // You can access the new user via result.user
      // Additional user info profile not available via:
      // result.additionalUserInfo.profile == null
      // You can check if the user is new or existing:
      // result.additionalUserInfo.isNewUser
    })
    .catch((error) => {
      // Some error occurred, you can inspect the code: error.code
      // Common errors could be invalid email and invalid or expired OTPs.
    });
}

إكمال تسجيل الدخول في تطبيق للأجهزة الجوّالة

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

لمعرفة المزيد من المعلومات حول كيفية التعامل مع عملية تسجيل الدخول باستخدام رابط بريد إلكتروني في تطبيق Android، يمكنك الرجوع إلى دليل Android.

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

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

سيكون الاختلاف في النصف الثاني من العملية:

واجهة برمجة التطبيقات Web modular API

import { getAuth, linkWithCredential, EmailAuthProvider } from "firebase/auth";

// Construct the email link credential from the current URL.
const credential = EmailAuthProvider.credentialWithLink(
  email, window.location.href);

// Link the credential to the current user.
const auth = getAuth();
linkWithCredential(auth.currentUser, credential)
  .then((usercred) => {
    // The provider is now successfully linked.
    // The phone user can now sign in with their phone number or email.
  })
  .catch((error) => {
    // Some error occurred.
  });

واجهة برمجة التطبيقات لمساحة الاسم على الويب

// Construct the email link credential from the current URL.
var credential = firebase.auth.EmailAuthProvider.credentialWithLink(
  email, window.location.href);

// Link the credential to the current user.
firebase.auth().currentUser.linkWithCredential(credential)
  .then((usercred) => {
    // The provider is now successfully linked.
    // The phone user can now sign in with their phone number or email.
  })
  .catch((error) => {
    // Some error occurred.
  });

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

واجهة برمجة التطبيقات Web modular API

import { getAuth, reauthenticateWithCredential, EmailAuthProvider } from "firebase/auth";

// Construct the email link credential from the current URL.
const credential = EmailAuthProvider.credentialWithLink(
  email, window.location.href);

// Re-authenticate the user with this credential.
const auth = getAuth();
reauthenticateWithCredential(auth.currentUser, credential)
  .then((usercred) => {
    // The user is now successfully re-authenticated and can execute sensitive
    // operations.
  })
  .catch((error) => {
    // Some error occurred.
  });

واجهة برمجة التطبيقات لمساحة الاسم على الويب

// Construct the email link credential from the current URL.
var credential = firebase.auth.EmailAuthProvider.credentialWithLink(
  email, window.location.href);

// Re-authenticate the user with this credential.
firebase.auth().currentUser.reauthenticateWithCredential(credential)
  .then((usercred) => {
    // The user is now successfully re-authenticated and can execute sensitive
    // operations.
  })
  .catch((error) => {
    // Some error occurred.
  });

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

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

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

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

نموذج البريد الإلكتروني التلقائي لتسجيل الدخول باستخدام الرابط

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

ينطبق هذا النموذج على اللغات التالية:

الرمز اللغة
ar العربية
zh-CN الصينية (المبسطة)
zh-tw الصينية (التقليدية)
الهولندية الهولندية
en الإنجليزية
en-GB الإنجليزية (المملكة المتحدة)
fr مأكولات فرنسية
de الألمانية
المعرّف الإندونيسية
it مأكولات إيطالية
ja مأكولات يابانية
ko الكورية
pl البولندية
pt-br البرتغالية (البرازيل)
البرتغالية (PT) برتغالي (البرتغال)
ru الروسية
. مأكولات إسبانية
es-419 الإسبانية (أمريكا اللاتينية)
th مأكولات تايلاندية

الخطوات اللاحقة

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

  • الطريقة التي ننصح بها في تطبيقاتك لمعرفة حالة المصادقة للمستخدم هي ضبط مراقب على كائن Auth. يمكنك بعد ذلك الحصول على معلومات الملف الشخصي الأساسية للمستخدم من كائن User. يُرجى الاطّلاع على إدارة المستخدمين.

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

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

لتسجيل خروج مستخدم، يمكنك الاتصال بالرقم signOut:

واجهة برمجة التطبيقات Web modular API

import { getAuth, signOut } from "firebase/auth";

const auth = getAuth();
signOut(auth).then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});

واجهة برمجة التطبيقات لمساحة الاسم على الويب

firebase.auth().signOut().then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});