Prácticas recomendadas para usar signInWithRedirect en navegadores que bloquean el acceso al almacenamiento de terceros

En este documento, se describen las prácticas recomendadas para usar accesos con redireccionamiento en navegadores que bloquean cookies de terceros. Debes seguir una de las opciones que se mencionan aquí para que signInWithRedirect() funcione según lo previsto en los entornos de producción y en todos los navegadores.

Descripción general

Para que el flujo de signInWithRedirect() sea óptimo para ti y los usuarios, el SDK de JavaScript de Firebase Authentication usa un iframe de multiorigen 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 opciones de configuración 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 un subdominio de web.app, usa la opción 1.
  • Si alojas tu app con un servicio que no sea Firebase, usa la opción 2, la 3, la 4 o la 5.

Opció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 opción diferente).

Si quieres 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.

    Del mismo modo, si usas un proveedor de SAML, agrega el authDomain nuevo a la URL de ACS del servicio de confirmación de consumidores de SAML.

Opció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.

API modular web

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

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

API con espacio de nombres 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());
```

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 opciones.

Opció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 opció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 que se indican en la opción 1 para actualizar las URL autorizadas de redirect_uri, ACS y authDomain. Una vez que vuelvas a implementar la app, el acceso al almacenamiento de origen cruzado ya no debería ocurrir.

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

Otra forma de eliminar el acceso al almacenamiento de origen cruzado es alojar por cuenta propia el código auxiliar de acceso de Firebase. Sin embargo, este enfoque no funciona para el acceso con Apple o SAML. Usa esta opción solo si la configuración del proxy inverso en la opción 3 es inviable.

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. Te recomendamos descargar y sincronizar los archivos de forma periódica para garantizar que se detecten las correcciones de errores y las funciones más recientes.

  3. Sigue los pasos de la opció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.

Opció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:

API modular 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);

API con espacio de nombres 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);

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.