المصادقة مع 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

      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

      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

    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

    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

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

Web

// 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

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

// 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

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

// 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 الألمانية
id الإندونيسية
it مأكولات إيطالية
ja مأكولات يابانية
ko الكورية
pl البولندية
pt-br البرتغالية (البرازيل)
البرتغالية (PT) برتغالي (البرتغال)
ru الروسية
. مأكولات إسبانية
es-419 الإسبانية (أمريكا اللاتينية)
th مأكولات تايلاندية

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

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

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

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

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

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

Web

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

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

Web

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