Рекомендации по использованию SignInWithRedirect в браузерах, которые блокируют доступ к стороннему хранилищу

В этом документе описаны лучшие практики использования перенаправления при входе в систему в браузерах, блокирующих сторонние файлы cookie. Для корректной работы функции signInWithRedirect() в производственной среде и во всех браузерах необходимо следовать одному из перечисленных здесь вариантов.

Обзор

Для обеспечения бесперебойной работы функции signInWithRedirect() как для вас, так и для ваших пользователей, SDK Firebase Authentication JavaScript использует кросс-доменный iframe, который подключается к домену Firebase Hosting вашего приложения. Однако этот механизм не работает с браузерами, блокирующими доступ к сторонним хранилищам.

Поскольку просьба к пользователям отключить функцию разделения хранилища на разделы в браузере встречается крайне редко, вместо этого следует применить к вашему приложению один из следующих вариантов настройки, в зависимости от специфики вашего сценария использования.

  • Если ваше приложение размещено на Firebase Hosting на поддомене firebaseapp.com , эта проблема вас не затрагивает, и никаких действий не требуется.
  • Если вы размещаете свое приложение на Firebase Hosting на собственном домене или поддомене web.app , используйте Вариант 1 .
  • Если вы размещаете свое приложение с помощью сервиса, отличного от Firebase, используйте Вариант 2 , Вариант 3 , Вариант 4 или Вариант 5 .

Вариант 1: Обновите конфигурацию Firebase, чтобы использовать свой собственный домен в качестве authDomain

Если вы размещаете свое приложение на Firebase Hosting с использованием собственного домена, вы можете настроить Firebase SDK для использования вашего собственного домена в качестве authDomain . Это гарантирует, что ваше приложение и iframe аутентификации будут использовать один и тот же домен, что предотвратит проблемы со входом в систему. (Если вы не используете 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-провайдера. Способ выполнения этого действия зависит от провайдера, но в целом вы можете следовать разделу «Прежде чем начать» в документации любого провайдера (например, провайдера Facebook ). Обновленный URI для авторизации выглядит следующим образом https://<the-domain-that-serves-your-app>/__/auth/handler — завершающий /__/auth/handler важен.

    Аналогичным образом, если вы используете SAML-провайдер, добавьте новый authDomain к URL-адресу службы обработки утверждений SAML (ACS).

  2. Убедитесь, что ваш continue_uri находится в списке авторизованных доменов .

  3. При необходимости выполните повторное развертывание с использованием Firebase Hosting, чтобы получить самую актуальную версию файла конфигурации Firebase, размещенного по адресу /__/firebase/init.json .

Вариант 2: Переключиться на signInWithPopup()

Используйте 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());
```

Всплывающие окна при входе в систему не всегда удобны для пользователей — иногда они блокируются устройством или платформой, а для пользователей мобильных устройств процесс менее плавный. Если использование всплывающих окон является проблемой для вашего приложения, вам следует воспользоваться одним из других вариантов.

Вариант 3: Переадресация запросов аутентификации на firebaseapp.com

Процесс signInWithRedirect начинается с перенаправления с домена вашего приложения на домен, указанный в параметре authDomain в конфигурации Firebase (" .firebaseapp.com" (по умолчанию). authDomain содержит вспомогательный код для входа в систему, который перенаправляет на поставщика идентификации, который в случае успеха перенаправляет обратно на домен приложения.

Когда процесс аутентификации возвращается в домен вашего приложения, осуществляется доступ к хранилищу браузера домена вспомогательной функции входа в систему. Этот вариант, а также следующий (для самостоятельного размещения кода), исключают доступ к хранилищу из других источников, который в противном случае блокируется браузерами.

  1. Настройте обратный прокси на сервере вашего приложения, чтобы GET/POST-запросы к https://<app domain>/__/auth/ перенаправлялись на https://<project>.firebaseapp.com/__/auth/ . Убедитесь, что это перенаправление прозрачно для браузера; это невозможно сделать с помощью перенаправления 302.

    Если вы используете nginx для обслуживания своего собственного домена, конфигурация обратного прокси будет выглядеть следующим образом:

    # reverse proxy for signin-helpers for popup/redirect sign in.
    location /__/auth {
      proxy_pass https://<project>.firebaseapp.com;
    }
    
  2. Выполните действия, описанные в Варианте 1 , чтобы обновить authorized redirect_uri , URL-адрес ACS и ваш authDomain . После повторного развертывания приложения доступ к хранилищу из разных источников должен прекратиться.

Вариант 4: Разместите вспомогательный код для авторизации на собственном домене.

Ещё один способ исключить доступ к хранилищу из разных источников — разместить вспомогательный код Firebase для входа в систему на собственном сервере. Однако этот подход не работает для входа через Apple или SAML. Используйте этот вариант только в том случае, если настройка обратного прокси, описанная в варианте 3, невозможна.

Размещение вспомогательного кода включает в себя следующие шаги:

  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. Выполните действия, описанные в Варианте 1 , чтобы обновить authorized redirect_uri и ваш authDomain . После повторного развертывания приложения доступ к хранилищу из разных источников должен прекратиться.

Вариант 5: Самостоятельная обработка входа в систему провайдера.

SDK аутентификации Firebase предоставляет методы signInWithPopup() и signInWithRedirect() в качестве удобных способов обертывания сложной логики и избежания необходимости использования другого SDK. Вы можете полностью избежать использования любого из этих методов, самостоятельно войдя в свою учетную запись у провайдера, а затем используя signInWithCredential() для обмена учетных данных провайдера на учетные данные Firebase Authentication. Например, вы можете использовать пример кода SDK входа в Google , чтобы получить учетные данные учетной записи Google, а затем создать новый экземпляр учетных данных Google, выполнив следующий код:

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() остальная часть вашего приложения будет работать так же, как и раньше.

Инструкции по получению учетных данных Apple находятся здесь .