Esta es una introducción a las reglas de seguridad en Firebase, por qué se hacen, cómo se implementan y ejemplos sencillos para mantener seguros los datos de tu aplicación.
Firebase como Backend as a Service debe implementar reglas de seguridad para poder definir qué se puede hacer con los datos almacenados en la base de datos, quién puede leer o escribir, entre otras cosas.
Obviamente es algo necesario, porque si gestionas usuarios lo más seguro es que éstos escriban en algún momento datos privados, que no quieras que otros usuarios puedan leer. Si tienes roles en la aplicación y por ejemplo solo los administradores pueden crear determinados tipos de ítem, tendrás que proteger tu aplicación para que no todo el mundo pueda escribir en esos item.
En general, Firebase nos ofrece un sistema sencillo para escribir las reglas de seguridad de una aplicación, por medio de un archivo de texto que tiene notación JSON. Es fácil de realizar los primeros pasos, pero cuando tienes una aplicación grande con un montón de reglas éstas se hacen difíciles de leer o mantener, por lo que la recomendación nuestra es aprender "Bolt", un lenguaje propio de Firebase (bastante parecido a Javascript) que compila produciendo el JSON que necesitarás para implementar las reglas en tu backend. De momento no vamos a entrar todavía en Bolt, pero ahí queda el aviso.
Definir el JSON de las reglas de seguridad de Firebase
Como hemos dicho, las reglas de seguridad de Firebase son bastante fáciles de escribir, sin embargo, el lenguaje a veces es un poco abstracto. Además, dado que debemos escribir reglas que den cabida a todas las posibles situaciones, la dificultad puede ser elevada para dar con la fórmula correcta, sobre todo si no estás acostumbrado a trabajar con este sistema.
En este artículo vamos a experimentar reglas sencillas por lo que comprobarás que todo resulta bastante fácil. Luego en aplicaciones mayores será donde encontremos más problemas y dónde surgen las dudas. Llegaremos allí.
Comencemos echando un vistazo a las reglas de seguridad que encontramos en una aplicación firebase recién creada.
{
"rules": {
".read": true,
".write": true
}
}
Como ves se utiliza una notación JSON para definir las reglas en este caso estamos otorgando permisos de lectura y escritura para cualquier entidad que esté en nuestra base de datos Firebase.
La regla para el permiso de lectura comienza con ".read", mientras que la regla para el permiso de escritura se escribe en el ítem ".write". El valor true indica un permiso bajo cualquier situación, lógicamente esto está bien para que nuestra aplicación nos permita empezar a trabajar pero no será lo adecuado cuando pongamos esta aplicación en producción.
La estructura del archivo de reglas en JSON debe corresponder con la estructura que hayas definido en tu base de datos Firebase. De momento para nuestro ejemplo vamos a pensar que existirá una entidad llamada "perfiles". De ella colgaran todos los datos de los perfiles de usuario.
perfiles {
user_id1: {
name: "Miguel"
bio: "Fundador de DesarrolloWeb.com"
},
user_id2: {
name: "Alvaro"
bio: "Co-fundador de EscuelaIT"
}
}
Si esta fuera la única entidad en nuestra aplicación, podríamos tener una estructura de reglas de seguridad como la que sigue:
{
"rules": {
"perfiles": {
".read": true,
".write": false
}
}
}
Así estaríamos dando permisos de seguridad para permitir la lectura de todos los perfiles, pero no permitir la escritura.
Variables en el sistema de reglas de seguridad
Hasta ahora suponemos que no habrá problema alguno para entender todo este sistema. Sin embargo la cosa se va a ir complicando un poco si queremos ser más precisos con las cosas que se pueden hacer o no se pueden hacer en la aplicación.
Hemos dicho que cada usuario tiene su propio perfil, pero ahora nos dicen que solo debemos permitir que el perfil de usuario sea escrito por aquel usuario, dueño de su propia información perfil. Sin embargo, para nuestra aplicación sí que sería posible que un usuario sea capaz de leer el perfil de otro usuario, pero únicamente queremos dar acceso de lectura a usuarios correctamente autenticados en la aplicación.
Para cumplir esos requisitos necesitamos usar diversas variables que nos facilita Firebase cuando estamos escribiendo las reglas de seguridad. Hay unas cuantas variables que iremos viendo en este artículo y otros que le seguirán. De momento vamos a aprender a manejar las que necesitamos para las reglas que nos han pedido cubrir.
Identificador del usuario autenticado: A través de la variable "auth" tenemos disponible la propiedad "uid" que nos indica el identificador de un usuario Firebase. Si no hay un usuario logueado en la app, simplemente encontraremos null como valor de "auth".
Identificador de un item en una entidad: También es posible acceder al identificador del elemento que se pretende leer o escribir dentro de las reglas de seguridad. Por ejemplo, en nuestro ejemplo cada perfil está en un documento que cuelga del identificador del usuario. Si queremos usar ese identificador en una regla tenemos que declarar una "Variable $".
{
"rules": {
"perfiles": {
"$user_id": {
".read": true,
".write": false
}
}
}
}
Ahora dentro de las reglas ".read" o ".write" (o las mencionadas ".validate" que no estamos viendo todavía) podremos acceder a "$user_id" para saber el identificador del usuario que se intenta leer o escribir.
Reglas para satisfacer la seguridad de acceso a los datos de perfil de usuario
Sabemos que cuesta adaptarse a todos estos conocimientos, pero con lo que hemos explicado deberías poder entender estas reglas de seguridad implementadas.
{
"rules": {
"perfiles": {
"$user_id": {
".read": "auth != null",
".write": "$user_id === auth.uid"
}
}
}
}
Básicamente estamos aplicando seguridad a la entidad "perfiles". Dentro de la entidad tenemos declarada la "Variable $" "$user_id" que nos dice cuál es el identificado de usuario que se está intentando leer o escribir.
".read": "auth != null",
Esto quiere decir que, cuando el usuario autenticado sea distinto de null (tenemos cualquier usuario correctamente logueado) se otorgará permiso de lectura.
".write": "$user_id === auth.uid"
Esto quiere decir que el permiso de escritura sólo se concederá cuando el identificador del usuario al que se pretende acceder sea igual del identificador de usuario que está logueado en el sistema.
Conclusión
Comenzar a usar las reglas de seguridad de Firebase es sencillo, sin embargo si quieres ser preciso y muy específico comienzan a encontarse problemas, básicamente porque el JSON se hace un poco lioso de escribir y difícil de mantener. La seguridad es un tema muy importante y hay que ser muy cuidadoso. Si quieres ser detallista observarás que necesitas bastante trabajo, algo que se soluciona muy bien cuando comienzas a usar "Bolt compiler".
Con esto que has aprendido tienes un pequeño porcentaje de los conocimientos necesarios para establecer las reglas de seguridad de tu aplicación, pero es un buen comienzo para ir practicando cosas. Nos quedan ver diversas otras variables disponibles, la validación de datos, el acceso a listados de items o a items particulares, varios niveles de "Variables $", el compilador "Bolt" y una buena cantidad de buenas prácticas y consideraciones para no dejar cabos sueltos en algo tan importante como es la seguridad.
Seguiremos explorando el sistema en nuevos artículos del Manual de Firebase. Mientras tanto te dejamos el vídeo donde explicamos las Regas de seguridad básicas en Firebase, seguro que le sacas un gran partido.
Miguel Angel Alvarez
Fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Com...