Condiciones de uso en las reglas de seguridad de Firebase Cloud Storage

Esta guía se basa en la sintaxis principal de la guía de lenguaje de las Reglas de seguridad de Firebase para mostrar cómo agregar condiciones a sus Reglas de seguridad de Firebase para el almacenamiento en la nube.

El componente principal de las reglas de seguridad de almacenamiento en la nube es la condición . Una condición es una expresión booleana que determina si se debe permitir o denegar una operación particular. Para reglas básicas, usar literales true y false como condiciones funciona perfectamente. Pero el lenguaje de las reglas de seguridad de Firebase para Cloud Storage le brinda formas de escribir condiciones más complejas que pueden:

  • Verificar autenticación de usuario
  • Validar datos entrantes

Autenticación

Firebase Security Rules para Cloud Storage se integra con Firebase Authentication para proporcionar una potente autenticación basada en usuarios para Cloud Storage. Esto permite un control de acceso granular basado en reclamos de un token de autenticación de Firebase.

Cuando un usuario autenticado realiza una solicitud en Cloud Storage, la variable request.auth se completa con el uid del usuario ( request.auth.uid ), así como con las reclamaciones del JWT de autenticación de Firebase ( request.auth.token ).

Además, cuando se utiliza la autenticación personalizada, aparecen reclamos adicionales en el campo request.auth.token .

Cuando un usuario no autenticado realiza una solicitud, la variable request.auth es null .

Al utilizar estos datos, existen varias formas comunes de utilizar la autenticación para proteger archivos:

  • Público: ignorar request.auth
  • Privado autenticado: verifique que request.auth no sea null
  • Usuario privado: verifique que request.auth.uid sea igual a un uid de ruta
  • Grupo privado: verifique que los reclamos del token personalizado coincidan con un reclamo elegido o lea los metadatos del archivo para ver si existe un campo de metadatos.

Público

Cualquier regla que no considere el contexto request.auth puede considerarse una regla public , ya que no considera el contexto de autenticación del usuario. Estas reglas pueden resultar útiles para mostrar datos públicos, como recursos de juegos, archivos de sonido u otro contenido estático.

// Anyone to read a public image if the file is less than 100kB
// Anyone can upload a public file ending in '.txt'
match /public/{imageId} {
  allow read: if resource.size < 100 * 1024;
  allow write: if imageId.matches(".*\\.txt");
}

Privado autenticado

En ciertos casos, es posible que desee que todos los usuarios autenticados de su aplicación puedan ver los datos, pero no los usuarios no autenticados. Dado que la variable request.auth es null para todos los usuarios no autenticados, todo lo que tiene que hacer es verificar que la variable request.auth exista para requerir autenticación:

// Require authentication on all internal image reads
match /internal/{imageId} {
  allow read: if request.auth != null;
}

Usuario privado

Con diferencia, el caso de uso más común de request.auth será proporcionar a los usuarios individuales permisos granulares sobre sus archivos: desde cargar imágenes de perfil hasta leer documentos privados.

Dado que los archivos en Cloud Storage tienen una "ruta" completa al archivo, todo lo que se necesita para que un archivo esté controlado por un usuario es una información única de identificación del usuario en el prefijo del nombre del archivo (como el uid del usuario) que se puede verificar. cuando se evalúa la regla:

// Only a user can upload their profile picture, but anyone can view it
match /users/{userId}/profilePicture.png {
  allow read;
  allow write: if request.auth.uid == userId;
}

grupo privado

Otro caso de uso igualmente común será permitir permisos de grupo sobre un objeto, como permitir que varios miembros del equipo colaboren en un documento compartido. Hay varios enfoques para hacer esto:

  • Crea un token personalizado de autenticación de Firebase que contiene información adicional sobre un miembro del grupo (como un ID de grupo).
  • Incluir información del grupo (como un ID de grupo o una lista de uid autorizados) en los metadatos del archivo.

Una vez que estos datos se almacenan en los metadatos del token o del archivo, se puede hacer referencia a ellos desde una regla:

// Allow reads if the group ID in your token matches the file metadata's `owner` property
// Allow writes if the group ID is in the user's custom token
match /files/{groupId}/{fileName} {
  allow read: if resource.metadata.owner == request.auth.token.groupId;
  allow write: if request.auth.token.groupId == groupId;
}

Solicitar evaluación

Las cargas, descargas, cambios de metadatos y eliminaciones se evalúan mediante la request enviada a Cloud Storage. Además de la ID única del usuario y la carga útil de Firebase Authentication en el objeto request.auth como se describe anteriormente, la variable de request contiene la ruta del archivo donde se realiza la solicitud, la hora en que se recibe la solicitud y el nuevo valor resource si la solicitud es por escrito.

El objeto request también contiene la identificación única del usuario y la carga útil de autenticación de Firebase en el objeto request.auth , que se explicará con más detalle en la sección Seguridad basada en el usuario de los documentos.

Una lista completa de propiedades en el objeto request está disponible a continuación:

Propiedad Tipo Descripción
auth mapa<cadena, cadena> Cuando un usuario inicia sesión, proporciona uid , el ID único del usuario, y token , un mapa de reclamaciones JWT de Firebase Authentication. De lo contrario, será null .
params mapa<cadena, cadena> Mapa que contiene los parámetros de consulta de la solicitud.
path camino Una path que representa la ruta en la que se realiza la solicitud.
resource mapa<cadena, cadena> El nuevo valor del recurso, presente solo en solicitudes write .
time marca de tiempo Una marca de tiempo que representa la hora del servidor en la que se evalúa la solicitud.

Evaluación de recursos

Al evaluar las reglas, es posible que también desee evaluar los metadatos del archivo que se carga, descarga, modifica o elimina. Esto le permite crear reglas complejas y poderosas que hacen cosas como permitir que solo se carguen archivos con ciertos tipos de contenido o que solo se eliminen archivos mayores a un cierto tamaño.

Las reglas de seguridad de Firebase para Cloud Storage proporcionan metadatos de archivos en el objeto resource , que contiene pares clave/valor de los metadatos que aparecen en un objeto de Cloud Storage. Estas propiedades se pueden inspeccionar en solicitudes de read o write para garantizar la integridad de los datos.

En solicitudes write (como cargas, actualizaciones de metadatos y eliminaciones), además del objeto resource , que contiene metadatos del archivo que existe actualmente en la ruta de la solicitud, también tiene la posibilidad de utilizar el objeto request.resource , que contiene un subconjunto de los metadatos del archivo que se escribirán si se permite la escritura. Puede utilizar estos dos valores para garantizar la integridad de los datos o imponer restricciones de la aplicación, como el tipo o el tamaño del archivo.

Una lista completa de propiedades en el objeto resource está disponible a continuación:

Propiedad Tipo Descripción
name cadena El nombre completo del objeto.
bucket cadena El nombre del depósito en el que reside este objeto.
generation En t La generación del objeto Google Cloud Storage de este objeto.
metageneration En t La metageneración del objeto Google Cloud Storage de este objeto.
size En t El tamaño del objeto en bytes.
timeCreated marca de tiempo Una marca de tiempo que representa la hora en que se creó un objeto.
updated marca de tiempo Una marca de tiempo que representa la hora en que se actualizó un objeto por última vez.
md5Hash cadena Un hash MD5 del objeto.
crc32c cadena Un hash crc32c del objeto.
etag cadena La etiqueta electrónica asociada con este objeto.
contentDisposition cadena La disposición del contenido asociada con este objeto.
contentEncoding cadena La codificación de contenido asociada con este objeto.
contentLanguage cadena El idioma del contenido asociado con este objeto.
contentType cadena El tipo de contenido asociado con este objeto.
metadata mapa<cadena, cadena> Pares clave/valor de metadatos personalizados adicionales especificados por el desarrollador.

request.resource contiene todos estos con la excepción de generation , metageneration , etag , timeCreated y updated .

Mejore con Cloud Firestore

Puede acceder a documentos en Cloud Firestore para evaluar otros criterios de autorización.

Al utilizar las funciones firestore.get() y firestore.exists() , tus reglas de seguridad pueden evaluar las solicitudes entrantes con respecto a documentos en Cloud Firestore. Las funciones firestore.get() y firestore.exists() esperan rutas de documentos completamente especificadas. Cuando use variables para construir rutas para firestore.get() y firestore.exists() , debe escapar explícitamente de las variables usando la sintaxis $(variable) .

En el siguiente ejemplo, vemos una regla que restringe el acceso de lectura a archivos a aquellos usuarios que son miembros de clubes particulares.

service firebase.storage {
  match /b/{bucket}/o {
    match /users/{club}/files/{fileId} {
      allow read: if club in
        firestore.get(/databases/(default)/documents/users/$(request.auth.id)).memberships
    }
  }
}
En el siguiente ejemplo, sólo los amigos de un usuario pueden ver sus fotos.
service firebase.storage {
  match /b/{bucket}/o {
    match /users/{userId}/photos/{fileId} {
      allow read: if
        firestore.exists(/databases/(default)/documents/users/$(userId)/friends/$(request.auth.id))
    }
  }
}

Una vez que cree y guarde sus primeras reglas de seguridad de Cloud Storage que utilizan estas funciones de Cloud Firestore, se le solicitará en Firebase console o Firebase CLI que habilite permisos para conectar los dos productos.

Puedes desactivar la función eliminando una función de IAM, como se describe en Administrar e implementar reglas de seguridad de Firebase .

Validar datos

Las reglas de seguridad de Firebase para almacenamiento en la nube también se pueden usar para la validación de datos, incluida la validación del nombre y la ruta del archivo, así como las propiedades de los metadatos del archivo, como contentType y size .

service firebase.storage {
  match /b/{bucket}/o {
    match /images/{imageId} {
      // Only allow uploads of any image file that's less than 5MB
      allow write: if request.resource.size < 5 * 1024 * 1024
                   && request.resource.contentType.matches('image/.*');
    }
  }
}

Funciones personalizadas

A medida que sus reglas de seguridad de Firebase se vuelven más complejas, es posible que desee incluir conjuntos de condiciones en funciones que pueda reutilizar en todo su conjunto de reglas. Las reglas de seguridad admiten funciones personalizadas. La sintaxis de las funciones personalizadas es un poco parecida a JavaScript, pero las funciones de las reglas de seguridad de Firebase están escritas en un lenguaje específico de dominio que tiene algunas limitaciones importantes:

  • Las funciones pueden contener solo una única declaración return . No pueden contener ninguna lógica adicional. Por ejemplo, no pueden ejecutar bucles ni llamar a servicios externos.
  • Las funciones pueden acceder automáticamente a funciones y variables desde el ámbito en el que están definidas. Por ejemplo, una función definida dentro del alcance del service firebase.storage tiene acceso a la variable resource y, solo para Cloud Firestore, funciones integradas como get() y exists() .
  • Las funciones pueden llamar a otras funciones pero no pueden repetirse. La profundidad total de la pila de llamadas está limitada a 10.
  • En la versión rules2 , las funciones pueden definir variables usando la palabra clave let . Las funciones pueden tener cualquier número de enlaces let, pero deben terminar con una declaración de devolución.

Una función se define con la palabra clave function y toma cero o más argumentos. Por ejemplo, es posible que desees combinar los dos tipos de condiciones utilizadas en los ejemplos anteriores en una sola función:

service firebase.storage {
  match /b/{bucket}/o {
    // True if the user is signed in or the requested data is 'public'
    function signedInOrPublic() {
      return request.auth.uid != null || resource.data.visibility == 'public';
    }
    match /images/{imageId} {
      allow read, write: if signedInOrPublic();
    }
    match /mp3s/{mp3Ids} {
      allow read: if signedInOrPublic();
    }
  }
}

El uso de funciones en sus reglas de seguridad de Firebase las hace más fáciles de mantener a medida que crece la complejidad de sus reglas.

Próximos pasos

Después de esta discusión sobre las condiciones, tendrá una comprensión más sofisticada de las reglas y estará listo para:

Aprenda a manejar casos de uso principales y conozca el flujo de trabajo para desarrollar, probar e implementar reglas: