احراز هویت با Firebase با استفاده از پیوندهای ایمیل

شما می‌توانید از احراز هویت فایربیس برای ورود کاربر استفاده کنید، به این صورت که ایمیلی حاوی یک لینک برای او ارسال می‌کنید که می‌تواند روی آن کلیک کند تا وارد سیستم شود. در این فرآیند، آدرس ایمیل کاربر نیز تأیید می‌شود.

مزایای بی‌شماری برای ورود از طریق ایمیل وجود دارد:

  • ثبت نام و ورود با کمترین اصطکاک.
  • کاهش ریسک استفاده مجدد از رمز عبور در برنامه‌های مختلف، که می‌تواند امنیت حتی رمزهای عبور خوب انتخاب شده را تضعیف کند.
  • امکان احراز هویت کاربر و در عین حال تأیید اینکه کاربر مالک قانونی آدرس ایمیل است.
  • کاربر برای ورود به سیستم فقط به یک حساب ایمیل قابل دسترسی نیاز دارد. نیازی به داشتن شماره تلفن یا حساب کاربری در شبکه‌های اجتماعی نیست.
  • کاربر می‌تواند بدون نیاز به ارائه (یا به خاطر سپردن) رمز عبور، که می‌تواند در دستگاه تلفن همراه دست و پا گیر باشد، به صورت ایمن وارد سیستم شود.
  • یک کاربر موجود که قبلاً با یک شناسه ایمیل (رمز عبور یا فدرال) وارد سیستم شده است، می‌تواند ارتقا یابد تا فقط با ایمیل وارد سیستم شود. به عنوان مثال، کاربری که رمز عبور خود را فراموش کرده است، همچنان می‌تواند بدون نیاز به تنظیم مجدد رمز عبور خود وارد سیستم شود.

قبل از اینکه شروع کنی

  1. اگر هنوز این کار را نکرده‌اید، مراحل موجود در راهنمای شروع به کار را دنبال کنید.

  2. ورود از طریق لینک ایمیل را برای پروژه Firebase خود فعال کنید.

    برای ورود کاربران از طریق لینک ایمیل، ابتدا باید متد ورود به سیستم ارائه دهنده ایمیل و لینک ایمیل را برای پروژه Firebase خود فعال کنید:

    1. در کنسول Firebase ، بخش Auth را باز کنید.
    2. در تب روش ورود ، گزینه ارائه دهنده ایمیل/رمز عبور را فعال کنید. توجه داشته باشید که برای استفاده از ورود از طریق لینک ایمیل، باید ورود از طریق ایمیل/رمز عبور فعال باشد.
    3. در همان بخش، روش ورود به سیستم با لینک ایمیل (ورود بدون رمز عبور) را فعال کنید.
    4. روی ذخیره کلیک کنید.

برای شروع جریان احراز هویت، رابطی ارائه دهید که کاربر را وادار به ارائه آدرس ایمیل خود کند و سپس تابع sendSignInLinkToEmail() را فراخوانی کنید تا از Firebase درخواست شود لینک احراز هویت را به ایمیل کاربر ارسال کند.

  1. شیء ActionCodeSettings را بسازید، که دستورالعمل‌هایی در مورد نحوه ساخت لینک ایمیل در Firebase ارائه می‌دهد. فیلدهای زیر را تنظیم کنید:

    • url : لینک عمیق برای جاسازی و هر وضعیت اضافی که باید منتقل شود. دامنه لینک باید در لیست دامنه‌های مجاز کنسول Firebase وجود داشته باشد که می‌توانید با رفتن به برگه تنظیمات (Authentication -> Settings -> Authorized Domains) آن را پیدا کنید. اگر برنامه روی دستگاه کاربر نصب نشده باشد و برنامه قادر به نصب نباشد، این لینک کاربر را به این URL هدایت می‌کند.

    • androidPackageName و IOSBundleId : برنامه‌هایی که هنگام باز شدن لینک ورود به سیستم در دستگاه اندروید یا iOS استفاده می‌شوند. درباره نحوه پیکربندی Firebase Dynamic Links برای باز کردن لینک‌های اقدام ایمیل از طریق برنامه‌های تلفن همراه بیشتر بیاموزید.

    • handleCodeInApp : روی true تنظیم شده است. عملیات ورود به سیستم برخلاف سایر اقدامات ایمیل خارج از باند (تنظیم مجدد رمز عبور و تأیید ایمیل) باید همیشه در برنامه انجام شود. دلیل این امر این است که در پایان جریان، انتظار می‌رود کاربر وارد سیستم شده باشد و وضعیت احراز هویت او در برنامه باقی بماند.

    • dynamicLinkDomain : (منسوخ شده، از linkDomain استفاده کنید) وقتی چندین دامنه لینک پویای سفارشی برای یک پروژه تعریف شده است، مشخص کنید که هنگام باز شدن لینک با استفاده از یک برنامه تلفن همراه مشخص (مثلاً example.page.link ) از کدام یک استفاده شود. در غیر این صورت، اولین دامنه به طور خودکار انتخاب می‌شود.

    • linkDomain : دامنه‌ی سفارشی اختیاری Firebase Hosting که هنگام باز شدن لینک با استفاده از یک برنامه‌ی موبایل مشخص استفاده می‌شود. این دامنه باید در Firebase Hosting پیکربندی شده و متعلق به پروژه باشد. این نمی‌تواند یک دامنه‌ی پیش‌فرض Hosting ( 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 استفاده می‌کنید تا از رهگیری احتمالی لینک شما توسط سرورهای واسطه جلوگیری شود.

ورود کامل

پیوندهای پویای فایربیس منسوخ شده‌اند؛ اکنون از میزبانی فایربیس برای ارسال لینک ورود استفاده می‌شود. برای پیکربندی خاص پلتفرم، راهنماها را دنبال کنید:

برای تکمیل ورود به سیستم از طریق برنامه تلفن همراه، برنامه باید طوری پیکربندی شود که لینک برنامه ورودی را تشخیص دهد، لینک عمیق زیرین را تجزیه کند و سپس ورود به سیستم را تکمیل کند.

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

با این حال، از آنجایی که این جریان می‌تواند در دستگاه دیگری که کاربر اصلی وارد آن نشده است، پایان یابد، ممکن است این جریان تکمیل نشود. در این صورت، می‌توان خطایی به کاربر نشان داد تا او را مجبور به باز کردن لینک در همان دستگاه کند. می‌توان مقداری حالت را در لینک ارسال کرد تا اطلاعاتی در مورد نوع عملیات و شناسه کاربری کاربر ارائه دهد.

اگر پروژه خود را در تاریخ ۱۵ سپتامبر ۲۰۲۳ یا بعد از آن ایجاد کرده‌اید، محافظت از شمارش ایمیل به طور پیش‌فرض فعال است. این ویژگی امنیت حساب‌های کاربری پروژه شما را بهبود می‌بخشد، اما متد fetchSignInMethodsForEmail() را غیرفعال می‌کند، که قبلاً برای پیاده‌سازی جریان‌های شناسه-اول توصیه می‌کردیم.

اگرچه می‌توانید محافظت از شمارش ایمیل را برای پروژه خود غیرفعال کنید، اما توصیه می‌کنیم این کار را انجام ندهید.

برای جزئیات بیشتر به مستندات مربوط به حفاظت از شمارش ایمیل مراجعه کنید.

مراحل بعدی

پس از اینکه کاربر یک حساب کاربری جدید ایجاد کرد، این حساب به عنوان بخشی از پروژه Firebase شما ذخیره می‌شود و می‌تواند برای شناسایی کاربر در هر برنامه‌ای در پروژه شما، صرف نظر از اینکه کاربر از چه روشی برای ورود به سیستم استفاده کرده است، مورد استفاده قرار گیرد.

در برنامه‌های خود، می‌توانید اطلاعات اولیه پروفایل کاربر را از شیء User دریافت کنید. به بخش مدیریت کاربران مراجعه کنید.

در قوانین امنیتی پایگاه داده و فضای ابری Firebase Realtime، می‌توانید شناسه کاربری منحصر به فرد کاربر وارد شده را از متغیر auth دریافت کنید و از آن برای کنترل داده‌هایی که کاربر می‌تواند به آنها دسترسی داشته باشد، استفاده کنید.

شما می‌توانید با پیوند دادن اعتبارنامه‌های ارائه‌دهنده‌ی احراز هویت (auth provider credentials ) به یک حساب کاربری موجود، به کاربران اجازه دهید با استفاده از چندین ارائه‌دهنده‌ی احراز هویت به برنامه‌ی شما وارد شوند.

برای خروج کاربر، تابع signOut() را فراخوانی کنید:

await FirebaseAuth.instance.signOut();