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

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

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

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

قبل ان تبدأ

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

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

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

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

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

    • url : الرابط العميق المراد تضمينه وأي حالة إضافية سيتم تمريرها. يجب إضافة مجال الرابط في قائمة Firebase Console للنطاقات المعتمدة، والتي يمكن العثور عليها بالانتقال إلى علامة تبويب طريقة تسجيل الدخول (المصادقة -> الإعدادات).
    • android و ios : التطبيقات التي سيتم استخدامها عند فتح رابط تسجيل الدخول على جهاز Android أو Apple. تعرف على المزيد حول كيفية تكوين روابط Firebase الديناميكية لفتح روابط إجراءات البريد الإلكتروني عبر تطبيقات الهاتف المحمول.
    • handleCodeInApp : اضبط على true. يجب أن تكتمل عملية تسجيل الدخول دائمًا في التطبيق بخلاف إجراءات البريد الإلكتروني الأخرى خارج النطاق (إعادة تعيين كلمة المرور والتحقق من البريد الإلكتروني). وذلك لأنه، في نهاية التدفق، من المتوقع أن يقوم المستخدم بتسجيل الدخول وأن تستمر حالة المصادقة الخاصة به داخل التطبيق.
    • 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'
      };

      Web namespaced API

      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;
        // ...
      });

    Web namespaced API

    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 Auth تقديم عنوان البريد الإلكتروني للمستخدم عند إكمال تدفق تسجيل الدخول. لكي تنجح عملية تسجيل الدخول، يجب أن يتطابق عنوان البريد الإلكتروني هذا مع العنوان الذي تم إرسال رابط تسجيل الدخول إليه في الأصل.

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

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

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

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

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

لإكمال تسجيل الدخول على الصفحة المقصودة، اتصل بـ 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 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.
    });
}

Web namespaced API

// 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.
  });

Web namespaced API

// 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.
  });

Web namespaced API

// 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() ، والتي أوصينا بها سابقًا لتنفيذ تدفقات المعرف أولاً.

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

راجع الوثائق الخاصة بحماية تعداد البريد الإلكتروني لمزيد من التفاصيل.

قالب البريد الإلكتروني الافتراضي لتسجيل الدخول بالارتباط

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

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

شفرة لغة
ع عربي
زه-CN الصينية المبسطة)
زه-TW تقاليد صينية)
nl هولندي
أون إنجليزي
ar-GB الإنجليزية (المملكة المتحدة)
الاب فرنسي
دي ألمانية
بطاقة تعريف الاندونيسية
هو - هي ايطالي
جا اليابانية
كو الكورية
رر تلميع
حزب العمال-BR البرتغالية (البرازيل).
حزب العمال-PT البرتغالية (البرتغال)
رو الروسية
وفاق الأسبانية
وفاق-419 الإسبانية (أمريكا اللاتينية)
ذ التايلاندية

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

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

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

  • في قاعدة بيانات Firebase Realtime وقواعد أمان التخزين السحابي، يمكنك الحصول على معرف المستخدم الفريد للمستخدم الذي قام بتسجيل الدخول من متغير 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.
});

Web namespaced API

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