بهترین روش‌ها برای استفاده از signInWithRedirect در مرورگرهایی که دسترسی به ذخیره‌سازی شخص ثالث را مسدود می‌کنند

این سند بهترین شیوه‌ها برای استفاده از ورودهای ریدایرکت در مرورگرهایی که کوکی‌های شخص ثالث را مسدود می‌کنند، شرح می‌دهد. برای اینکه signInWithRedirect() در محیط‌های عملیاتی و در همه مرورگرها مطابق انتظار عمل کند، باید یکی از گزینه‌های ذکر شده در اینجا را دنبال کنید.

نمای کلی

برای اینکه تابع signInWithRedirect() برای شما و کاربرانتان روان و بدون مشکل اجرا شود، کیت توسعه نرم‌افزار جاوا اسکریپت احراز هویت فایربیس از یک iframe با مبدا متقابل استفاده می‌کند که به دامنه میزبانی فایربیس برنامه شما متصل می‌شود. با این حال، این مکانیزم با مرورگرهایی که دسترسی به فضای ذخیره‌سازی شخص ثالث را مسدود می‌کنند، کار نمی‌کند.

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

  • اگر برنامه خود را با Firebase Hosting در زیر دامنه firebaseapp.com میزبانی می‌کنید، تحت تأثیر این مشکل قرار نمی‌گیرید و نیازی به اقدامی نیست.
  • اگر برنامه خود را با Firebase Hosting روی یک دامنه سفارشی یا زیر دامنه web.app میزبانی می‌کنید، از گزینه ۱ استفاده کنید.
  • اگر برنامه خود را با سرویسی غیر از Firebase میزبانی می‌کنید، از گزینه ۲ ، گزینه ۳ ، گزینه ۴ یا گزینه ۵ استفاده کنید.

گزینه ۱: پیکربندی Firebase خود را به‌روزرسانی کنید تا از دامنه سفارشی شما به عنوان authDomain استفاده شود

اگر برنامه خود را با Firebase Hosting و با استفاده از یک دامنه سفارشی میزبانی می‌کنید، می‌توانید Firebase SDK را طوری پیکربندی کنید که از دامنه سفارشی شما به عنوان authDomain استفاده کند. این کار تضمین می‌کند که برنامه شما و iframe مربوط به auth از یک دامنه استفاده می‌کنند که از مشکل ورود به سیستم جلوگیری می‌کند. (اگر از Firebase Hosting استفاده نمی‌کنید، باید از گزینه دیگری استفاده کنید.) مطمئن شوید که دامنه سفارشی را در همان پروژه‌ای که برای احراز هویت استفاده می‌کنید، تنظیم کرده‌اید.

برای به‌روزرسانی پیکربندی Firebase خود برای استفاده از دامنه سفارشی به عنوان دامنه احراز هویت، موارد زیر را انجام دهید:

  1. Firebase JS SDK را طوری پیکربندی کنید که از دامنه سفارشی شما به عنوان authDomain استفاده کند:

    const firebaseConfig = {
      apiKey: "<api-key>",
      authDomain: "<the-domain-that-serves-your-app>",
      databaseURL: "<database-url>",
      projectId: "<project-id>",
      appId: "<app-id>"
    };
    
  1. دامنه‌ی authDomain جدید را به فهرست URIهای ریدایرکت مجاز ارائه‌دهنده‌ی OAuth خود اضافه کنید. نحوه‌ی انجام این کار به ارائه‌دهنده بستگی دارد، اما به‌طورکلی می‌توانید برای دستورالعمل‌های دقیق، بخش «قبل از شروع» را در هر ارائه‌دهنده‌ای دنبال کنید (برای مثال، ارائه‌دهنده‌ی فیس‌بوک ). URI به‌روزرسانی‌شده برای تأیید به شکل https://<the-domain-that-serves-your-app>/__/auth/handler - /__/auth/handler انتهایی مهم است.

    به همین ترتیب، اگر از ارائه‌دهنده SAML استفاده می‌کنید، authDomain جدید را به URL سرویس مصرف‌کننده ادعای SAML (ACS) اضافه کنید.

  2. مطمئن شوید که continue_uri شما در فهرست دامنه‌های مجاز قرار دارد.

  3. در صورت نیاز، برای دریافت جدیدترین فایل پیکربندی Firebase که در /__/firebase/init.json قرار دارد، آن را با Firebase Hosting مجدداً مستقر کنید.

گزینه ۲: به تابع signInWithPopup() بروید

به جای signInWithRedirect() از signInWithPopup() signInWithRedirect() استفاده کنید. بقیه کد برنامه شما ثابت می‌ماند، اما شیء UserCredential به طور متفاوتی بازیابی می‌شود.

Web

  // Before
  // ==============
  signInWithRedirect(auth, new GoogleAuthProvider());
  // After the page redirects back
  const userCred = await getRedirectResult(auth);

  // After
  // ==============
  const userCred = await signInWithPopup(auth, new GoogleAuthProvider());

Web

  // Before
  // ==============
  firebase.auth().signInWithRedirect(new firebase.auth.GoogleAuthProvider());
  // After the page redirects back
  var userCred = await firebase.auth().getRedirectResult();

  // After
  // ==============
  var userCred = await firebase.auth().signInWithPopup(
      new firebase.auth.GoogleAuthProvider());
```

ورود به سیستم از طریق پاپ‌آپ همیشه برای کاربران ایده‌آل نیست—پاپ‌آپ‌ها گاهی اوقات توسط دستگاه یا پلتفرم مسدود می‌شوند و جریان برای کاربران تلفن همراه روان‌تر نیست. اگر استفاده از پاپ‌آپ‌ها برای برنامه شما مشکل‌ساز است، باید یکی از گزینه‌های دیگر را دنبال کنید.

گزینه ۳: درخواست‌های احراز هویت پروکسی به firebaseapp.com

جریان signInWithRedirect با هدایت از دامنه برنامه شما به دامنه مشخص شده در پارامتر authDomain در پیکربندی firebase شروع می‌شود (" authDomain میزبان کد کمکی ورود به سیستم است که به ارائه‌دهنده هویت هدایت می‌شود، که در صورت موفقیت، به دامنه برنامه هدایت می‌شود.

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

  1. یک پروکسی معکوس روی سرور برنامه خود تنظیم کنید تا درخواست‌های GET/POST به https://<app domain>/__/auth/ به https://<project>.firebaseapp.com/__/auth/ ارسال شوند. اطمینان حاصل کنید که این ارسال برای مرورگر شفاف است؛ این کار را نمی‌توان از طریق ریدایرکت 302 انجام داد.

    اگر از nginx برای ارائه دامنه سفارشی خود استفاده می‌کنید، پیکربندی reverse-proxy به این شکل خواهد بود:

    # reverse proxy for signin-helpers for popup/redirect sign in.
    location /__/auth {
      proxy_pass https://<project>.firebaseapp.com;
    }
    
  2. مراحل گزینه ۱ را برای به‌روزرسانی authorized redirect_uri ، ACS URL و authDomain خود دنبال کنید. پس از استقرار مجدد برنامه، دسترسی به فضای ذخیره‌سازی بین مبدا (cross-origin storage) دیگر نباید اتفاق بیفتد.

گزینه ۴: کد کمکی ورود را در دامنه خود میزبانی کنید

راه دیگر برای حذف دسترسی به فضای ذخیره‌سازی بین مبدا، میزبانی خودکار کد کمکی ورود به سیستم Firebase است. با این حال، این رویکرد برای ورود به سیستم Apple یا SAML کار نمی‌کند. فقط در صورتی از این گزینه استفاده کنید که راه‌اندازی پروکسی معکوس در گزینه ۳ امکان‌پذیر نباشد.

میزبانی کد کمکی مراحل زیر را دارد:

  1. با اجرای دستورات زیر، فایل‌ها را برای میزبانی از مسیر <project>.firebaseapp.com دانلود کنید:

    mkdir signin_helpers/ && cd signin_helpers
    wget https://<project>.firebaseapp.com/__/auth/handler
    wget https://<project>.firebaseapp.com/__/auth/handler.js
    wget https://<project>.firebaseapp.com/__/auth/experiments.js
    wget https://<project>.firebaseapp.com/__/auth/iframe
    wget https://<project>.firebaseapp.com/__/auth/iframe.js
    wget https://<project>.firebaseapp.com/__/auth/links
    wget https://<project>.firebaseapp.com/__/auth/links.js
    wget https://<project>.firebaseapp.com/__/firebase/init.json
    
  2. فایل‌های فوق را تحت دامنه برنامه خود میزبانی کنید. مطمئن شوید که وب سرور شما می‌تواند به https://<app domain>/__/auth/<filename> و https://<app domain>/__/firebase/init.json پاسخ دهد.

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

  3. مراحل گزینه ۱ را برای به‌روزرسانی authorized redirect_uri و authDomain خود دنبال کنید. پس از استقرار مجدد برنامه، دسترسی به فضای ذخیره‌سازی بین مبدا (cross-origin storage) دیگر نباید اتفاق بیفتد.

گزینه ۵: ورود به سیستم ارائه دهنده را به طور مستقل مدیریت کنید

کیت توسعه نرم‌افزاری احراز هویت فایربیس (Firebase Authentication SDK) متدهای signInWithPopup() و signInWithRedirect() را به عنوان متدهای کمکی برای پوشش منطق پیچیده و جلوگیری از نیاز به درگیر کردن SDK دیگر ارائه می‌دهد. شما می‌توانید با ورود مستقل به ارائه‌دهنده خود، و سپس استفاده از signInWithCredential() برای تبادل اعتبارنامه‌های ارائه‌دهنده با اعتبارنامه احراز هویت فایربیس، از استفاده کامل از هر دو روش اجتناب کنید. به عنوان مثال، می‌توانید از نمونه کد SDK ورود به سیستم گوگل (Google Sign In SDK) ، برای دریافت اعتبارنامه حساب گوگل استفاده کنید، سپس با اجرای کد زیر، یک اعتبارنامه گوگل جدید ایجاد کنید:

Web

  // `googleUser` from the onsuccess Google Sign In callback.
  //  googUser = gapi.auth2.getAuthInstance().currentUser.get();
  const credential = GoogleAuthProvider.credential(googleUser.getAuthResponse().id_token);
  const result = await signInWithCredential(auth, credential);

Web

  // `googleUser` from the onsuccess Google Sign In callback.
  const credential = firebase.auth.GoogleAuthProvider.credential(
      googleUser.getAuthResponse().id_token);
  const result = await firebase.auth().signInWithCredential(credential);

بعد از اینکه signInWithCredential() فراخوانی کردید، بقیه‌ی برنامه‌ی شما مانند قبل عمل می‌کند.

دستورالعمل‌های دریافت اعتبارنامه اپل در اینجا آمده است.