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

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

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

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

قبل ان تبدأ

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

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

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

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

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

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

      إصدار الويب 9

      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'
      };

      إصدار الويب 8

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

    إصدار الويب 9

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

    إصدار الويب 8

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

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

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

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

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

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

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

إصدار الويب 9

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

إصدار الويب 8

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

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

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

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

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

إصدار الويب 9

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

إصدار الويب 8

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

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

إصدار الويب 9

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

إصدار الويب 8

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

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

في حال كنت دعم كل كلمة المرور و تسجيل الدخول مع البريد الإلكتروني، للتمييز بين طريقة تسجيل الدخول للمستخدم كلمة السر / وصلة، استخدام القائمة على صلة fetchSignInMethodsForEmail . يُعد هذا مفيدًا لعمليات تدفقات المعرف أولاً حيث يُطلب من المستخدم أولاً تقديم بريده الإلكتروني ثم تقديم طريقة تسجيل الدخول:

إصدار الويب 9

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

// After asking the user for their email.
const email = window.prompt('Please provide your email');

const auth = getAuth();
fetchSignInMethodsForEmail(auth, email)
  .then((signInMethods) => {
    // This returns the same array as fetchProvidersForEmail but for email
    // provider identified by 'password' string, signInMethods would contain 2
    // different strings:
    // 'emailLink' if the user previously signed in with an email/link
    // 'password' if the user has a password.
    // A user could have both.
    if (signInMethods.indexOf(EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD) != -1) {
      // User can sign in with email/password.
    }
    if (signInMethods.indexOf(EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD) != -1) {
      // User can sign in with email/link.
    }
  })
  .catch((error) => {
    // Some error occurred, you can inspect the code: error.code
  });

إصدار الويب 8

// After asking the user for their email.
var email = window.prompt('Please provide your email');
firebase.auth().fetchSignInMethodsForEmail(email)
  .then((signInMethods) => {
    // This returns the same array as fetchProvidersForEmail but for email
    // provider identified by 'password' string, signInMethods would contain 2
    // different strings:
    // 'emailLink' if the user previously signed in with an email/link
    // 'password' if the user has a password.
    // A user could have both.
    if (signInMethods.indexOf(
            firebase.auth.EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD) != -1) {
      // User can sign in with email/password.
    }
    if (signInMethods.indexOf(
            firebase.auth.EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD) != -1) {
      // User can sign in with email/link.
    }
  })
  .catch((error) => {
    // Some error occurred, you can inspect the code: error.code
  });

كما هو موضح أعلاه البريد الإلكتروني / كلمة المرور والبريد الإلكتروني / رابط تعتبر نفسها firebase.auth.EmailAuthProvider (نفس PROVIDER_ID ) مع أساليب مختلفة من تسجيل الدخول.

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

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

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

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

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

تسجيل الخروج مستخدم، استدعاء signOut :

إصدار الويب 9

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

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

إصدار الويب 8

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