Reglas de seguridad en Cloud Firestore: Protección de escritura en campos de un documento

Maribel Maisano
Droid LATAM
Published in
3 min readFeb 21, 2020
Photo by Rob King on Unsplash

Si haces uso de la base de datos en tiempo real de Firebase en tus aplicaciones, es posible que alguna vez hayas recibido la notificación de que tu implementación contiene reglas inseguras. Esto quiere decir que los documentos de tu base de datos son accesibles sin límite de algún tipo. De esta forma, cualquier usuario malintencionado que logre averiguar el ID de tu proyecto será capaz de leer, modificar o borrar los datos.

Pero ¿qué tipo de seguridad podemos aplicar entonces?

Para comenzar a comprender, debemos saber que podemos limitar cuatro tipos de operaciones sobre nuestros documentos:

  • Lectura
  • Creación
  • Modificación
  • Borrado

Las reglas que podemos aplicar se encuentran fuertemente ligadas a la implementación de Firebase Authentication en nuestra aplicación, ya que de esta manera podemos saber cuál es el usuario que intenta realizar una operación y saber si tiene permiso para hacerla o no.

Escribiremos nuestras reglas desde la consola de Firebase o bien localmente para luego desplegarlas a través de Firebase CLI. De ambas formas, la sintaxis es la misma.

Ejemplo de aplicación de reglas

Tomemos el ejemplo de una aplicación de tipo multijugador. Tendremos una colección de partidas que contendrá, entre otra información, el uid de cada jugador que participa y el puntaje de cada uno de ellos como campos que llamaremos: idJugador1, idJugador2, puntajeJugador1, puntajeJugador2.

Definamos inicialmente las reglas que permiten que cualquier jugador que haya iniciado sesión puede leer la tabla partidas y crear nuevas, pero ninguno de ellos puede borrar una partida:

Observemos que debemos especificar la ruta de la colección que queremos limitar y las operaciones por separado. Dentro de request.auth tenemos información sobre el usuario que está realizando la petición. Estas reglas que especificamos son a nivel documento.

Ahora digamos que queremos restringir la operación de edición para que cada usuario pueda modificar únicamente el puntaje que le pertenece y no el de su oponente. Comencemos por especificar que si el request proviene del jugador 1 solamente puede modificar el campo puntajeJugador1.

Para ello, vamos a definir una función que:

  1. Verifique cuál es el puntaje que se está intentando modificar.
  2. Decida si el usuario que está intentando hacerlo tiene permiso.

Por el momento, para saber cuál es el campo que se está queriendo modificar en la petición, la única forma que tenemos de hacerlo es comprobar si el valor que está contenido en la base de datos difiere del que proviene del request. Accedemos a los campos del documento guardado a través de resource.data y al payload del request en request.resource.data. Para saber si se está modificando el campo puntajeJugador1 o puntajeJugador2 compararemos los valores de la base de datos con los del request. Por último, dependiendo cuál sea, comprobaremos si el uid del usuario que intenta hacer la modificación coincide con el usuario dueño de ese puntaje.

Nuestras reglas actualizadas quedarían de la siguiente forma:

De esta forma hemos logrado que:

  • Cualquier usuario que haya iniciado sesión pueda leer las partidas y crear nuevas
  • Ningún usuario pueda eliminar partidas
  • Un usuario pueda modificar el puntaje solamente si le pertenece.

--

--

Maribel Maisano
Droid LATAM

Android Dev @ Equinox Media· WTM Ambassador @ GDG & WTM Buenos Aires