Mitiga el acceso con redireccionamiento dañado en los navegadores que bloquean el acceso al almacenamiento de terceros

En este documento, se describe cómo mitigar los accesos con redireccionamiento dañados en los navegadores que bloquean cookies de terceros.

Descripción general

A fin de que el flujo signInWithRedirect() sea óptimo para los desarrolladores de Firebase y sus usuarios, Firebase Authentication utiliza un iframe de origen cruzado que se conecta al dominio de Firebase Hosting de tu app. Sin embargo, este mecanismo no funciona con navegadores que bloquean el acceso al almacenamiento de terceros.

Dado que solicitar a los usuarios que inhabiliten las funciones de partición de almacenamiento en el navegador es pocas veces una opción, puedes aplicar una de las siguientes mitigaciones a tu app, en función de los detalles de tu caso de uso.

  • Si alojas tu app con Firebase Hosting en un subdominio de firebaseapp.com, este problema no te afectará y no deberás realizar ninguna acción.
  • Si alojas tu app con Firebase Hosting en un dominio personalizado (O web.app), usa la mitigación n° 1.
  • Si alojas tu app con un servicio que no sea Firebase, usa la mitigación n° 2, la n° 3, la n° 4 o la n° 5.

Mitigación n° 1: Actualiza la configuración de Firebase para usar tu dominio personalizado como authDomain

Si alojas tu app con Firebase Hosting mediante un dominio personalizado, puedes configurar el SDK de Firebase para usar tu dominio personalizado como authDomain. Esto garantiza que tu app y el iframe de autenticación usen el mismo dominio, lo que evita el problema de acceso. (Si no usas Firebase Hosting, debes usar una mitigación diferente).

A fin de actualizar la configuración de Firebase para usar tu dominio personalizado como dominio de autenticación, haz lo siguiente:

  1. Configura el SDK de Firebase JS para usar tu dominio personalizado como authDomain:

    const firebaseConfig = {
      apiKey: "<api-key>",
      authDomain: "<the-domain-that-serves-your-app>",
      databaseURL: "<database-url>",
      projectId: "<project-id>",
      appId: "<app-id>"
    };
    
  2. Agrega el nuevo authDomain a la lista de URIs de redireccionamiento autorizados de tu proveedor de OAuth. La forma de hacerlo dependerá del proveedor, pero en general, puedes consultar la sección “Antes de comenzar” en cualquier proveedor para obtener instrucciones específicas (por ejemplo, Proveedor de Facebook). El URI actualizado para autorizar se ve como https://<the-domain-that-serves-your-app>/__/auth/handler: el /__/auth/handler al final es importante.

Mitigación n° 2: Cambia a signInWithPopup()

Usa signInWithPopup() en lugar de signInWithRedirect(). El resto del código de tu app permanece igual, pero el objeto UserCredential se recupera de manera diferente.

Web version 9

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

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

Web version 8

  // 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());
```

El acceso emergente no siempre es ideal para los usuarios, ya que, a veces, el dispositivo o la plataforma bloquean las ventanas emergentes y el flujo es menos fluido para los usuarios de dispositivos móviles. Si el uso de ventanas emergentes es un problema para tu app, deberás aplicar una de las otras mitigaciones.

Mitigación n° 3: Envía solicitudes de autenticación de proxy a firebaseapp.com

El flujo signInWithRedirect comienza mediante el redireccionamiento del dominio de tu app al dominio especificado en el parámetro authDomain de la configuración de Firebase (“.firebaseapp.com” de forma predeterminada). authDomain aloja el código auxiliar de acceso que redirecciona al proveedor de identidad. Cuando este se ejecuta de forma correcta, redirecciona al dominio de la app.

Cuando el flujo de autenticación redirecciona al dominio de tu app, se accede al almacenamiento del navegador del dominio auxiliar de acceso. Esta mitigación y la siguiente (para alojar el código por cuenta propia) eliminan el acceso al almacenamiento de origen cruzado, que, de lo contrario, los navegadores bloquean.

  1. Configura un proxy inverso en el servidor de apps para que las solicitudes GET/POST a https://<app domain>/__/auth/ se reenvíen a https://<project>.firebaseapp.com/__/auth/. Asegúrate de que el reenvío sea transparente para el navegador. Esto no se puede hacer mediante un redireccionamiento 302.

    Si utilizas nginx para entregar tu dominio personalizado, la configuración del proxy inverso tendrá el siguiente aspecto:

    # reverse proxy for signin-helpers for popup/redirect sign in.
    location /__/auth {
      proxy_pass https://<project>.firebaseapp.com;
    }
    
  2. Sigue los pasos de la mitigación 1 para actualizar redirect_uri autorizados y authDomain. Una vez que vuelvas a implementar la app, el acceso al almacenamiento de origen cruzado ya no debería ocurrir.

Mitigación n° 4: Aloja por cuenta propia el código auxiliar de acceso en tu dominio

Sigue estos pasos para alojar el código auxiliar:

  1. Descarga los archivos para alojar desde la ubicación <project>.firebaseapp.com mediante la ejecución de los siguientes comandos:

    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
    
  2. Aloja los archivos anteriores en el dominio de tu app. Asegúrate de que tu servidor web pueda responder a https://<app domain>/__/auth/<filename>.

    A continuación, se presenta una implementación de servidor de muestra que descarga y aloja los archivos.

  3. Sigue los pasos de la mitigación 1 para actualizar redirect_uri autorizados y authDomain. Una vez que vuelvas a implementar la app, el acceso al almacenamiento de origen cruzado ya no debería ocurrir.

Mitigación n° 5: Controla el acceso de proveedor de forma independiente

El SDK de Firebase Authentication proporciona signInWithPopup() y signInWithRedirect() como métodos útiles para unir las lógicas complicadas y evitar tener que involucrar otro SDK. A fin de evitar por completo el uso de cualquiera de los dos métodos, accede de forma independiente a tu proveedor y, luego, usa signInWithCredential() para intercambiar las credenciales del proveedor por una credencial de Firebase Authentication. Por ejemplo, puedes usar el código de muestra del SDK de Acceso con Google para obtener una credencial de Cuenta de Google y, luego, crear una instancia de una nueva credencial de Google mediante la ejecución del siguiente código:

Web version 9

  // `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 version 8

  // `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);

Después de llamar a signInWithCredential(), el resto de la app funcionará igual que antes.

Aquí encontrarás las instrucciones para obtener una credencial de Apple.