Publicado el 14.05.2022 a las 10:51
En este artículo te explicaré cómo usar las reglas de seguridad de Firebase Realtime Database para bastionar tu base de datos
Esta semana he comenzado a recibir avisos en mi consola de Firebase de que una de mis bases de datos de Realtime Database no tenía reglas seguras.
Las reglas que tenía implementadas eran las típicas de permitir acceso de lectura y escritura a cualquiera que estuviera logueado en mi aplicación:
{ "rules": { ".read": "auth.uid!=null", ".write": "auth.uid!=null", } }
Pero parece que eso ha empezado a no ser suficiente para Firebase como seguridad para la base de datos, ya que la advertencia decía que cualquiera que estuviera logueado podía acceder a toda la información de la base de datos y eso no era seguro.
Como es cierto que no es lo mejor, me puse a estudiar cómo mejorar la seguridad en el acceso de los datos en RealTime Database y como me ocurre casi siempre, los mejores recursos para aprender algo sobre Firebase los encuentro en su documentación oficial.
Estos han sido mis aprendizajes y conclusiones:
Imagina que tienes varios clientes (por ejemplo varias tiendas) en tu base de datos, pues he añadido para cada tienda una lista de usuarios donde iré almacenando los UID de los usuarios que se registren para esa tienda.
De esta forma, cada usuario sólo podrá leer y escribir sobre los datos de la tienda en la que esté registrado.
{ "rules": { "$storeId":{ ".read": "data.child('users').hasChildren([auth.uid])"", ".write": "data.child('users').hasChildren([auth.uid])", } } }
".read"
".write"
".validate"
".indexOn"
El siguiente ejemplo permitirá añadir datos a la base de datos siempre y cuando esos datos contengan un email, un userId y un Name
".write":"data.child('fjmartinez').child('name').child('userid').child('email').exists()"
Comienzo todos mis proyectos así y poco a poco voy añadiendo reglas
{ "rules": { ".read": true, ".write": true } }
Si encontraras abusos a tu base de datos puedes escribir estas reglas para que nadie pueda leer ni escribir hasta que solventes el problema.
{ "rules": { ".read": false, ".write": false } }
{ "rules": { ".read": "auth.uid!=null", ".write": "auth.uid!=null", } }
{ "rules": { ".read": “auth.token.email.endsWith(‘@domain.com’)”, ".write": “auth.token.email.endsWith(‘@domain.com’)” } }
Acceso a los datos del usuario que estarán dentro del nodo con su uid y a su vez dentro del nodo users
{ "rules": { "users": { "$uid": { ".read": "$uid === auth.uid", ".write": "$uid === auth.uid" } } } }
{ "rules": { "posts": { "$uid": { ".write": "root.child('users').child('admin').val() === true" } } } }
{ "rules": { "posts": { "$uid": { ".validate": "newData.isString() && newData.val().length > 0 && newData.val().length <= 140" } } } }
{ "rules": { "posts": { "$uid": { ".validate": "newData.hasChildren(['username', 'timestamp'])" } } } }
{ "rules": { "posts": { "$uid": { "timestamp": { ".validate": "newData.val() <= now" } } } } }
{ "rules": { "posts": { "$uid": { ".write": "!data.exists()" } } } }
{ "rules": { "posts": { "$uid": { ".write": "newData.exists()" } } } }
{ "rules": { "posts": { "$uid": { ".write": "!data.exists() || !newData.exists()" } } } }
{ "rules": { "posts": { "$uid": { ".write": "data.exists() && newData.exists()" } } } }
Hasta luego 🖖