Capítulo 32 — Cloud Storage Security Rules: Protegiendo archivos en Firebase¶
Recursos visuales propuestos¶
Antes de desarrollar este capítulo conviene distinguir entre recursos pedagógicos para explicar conceptos de seguridad de archivos y recursos técnicos que representan la arquitectura real de autorización. El flujo de autorización para un archivo, la comparación entre archivo público y privado, la organización de carpetas protegidas, los ejemplos de restricciones por tipo de archivo y los casos de uso deben presentarse como imágenes didácticas, porque ayudan a fijar criterios de diseño y a visualizar escenarios frecuentes sin necesidad de describir internamente todos los componentes de la plataforma. En cambio, la arquitectura Cliente → Storage → Security Rules, el flujo completo de autorización, la integración entre Authentication, Firestore y Storage, y la arquitectura de protección del almacenamiento del proyecto oficial deben representarse como diagramas SVG, ya que requieren mostrar identidad, rutas, motor de evaluación, metadatos, datos auxiliares y decisiones de acceso entre múltiples servicios.[cite:1][cite:2]
Imágenes didácticas¶
- Flujo de autorización para un archivo. Conviene como imagen didáctica porque ayuda a comprender rápidamente el paso de solicitud, evaluación y decisión.[cite:1]
- Comparación entre archivo público y privado. Funciona mejor como imagen didáctica por su carácter comparativo y conceptual.
- Organización de carpetas protegidas. Debe ser imagen didáctica porque el objetivo principal es explicar diseño lógico de paths y segmentación de acceso.
- Ejemplos de restricciones por tipo de archivo. Se entiende mejor como imagen didáctica al mostrar reglas por MIME, extensión y tamaño.[cite:1][cite:2]
- Casos de uso. Conviene presentarlos como imágenes didácticas para resumir fotografías, evidencias, expedientes y recursos multimedia.
Diagramas SVG¶
- Arquitectura Cliente → Storage → Security Rules. Debe ser SVG porque representa el pipeline de autorización path-based en Cloud Storage.[cite:1]
- Flujo completo de autorización. Debe ser SVG porque integra
request,resource,request.resource,authy resultado booleano.[cite:2] - Integración entre Authentication, Firestore y Storage. Debe ser SVG porque muestra cómo las reglas de Storage pueden apoyarse en autenticación y documentos de Firestore.[cite:2]
- Arquitectura de protección del almacenamiento del proyecto oficial. Debe ser SVG porque requiere representar módulos, carpetas virtuales, claims, metadatos y reglas diferenciadas por rol.
Objetivos de aprendizaje¶
Al finalizar este capítulo, el lector será capaz de:
- Comprender qué son las Cloud Storage Security Rules y por qué son la capa central de autorización para archivos en Firebase.[cite:1]
- Explicar cómo Storage evalúa solicitudes usando
request,resource,request.resource,auth,metadataytime.[cite:2] - Diseñar reglas de acceso para documentos, imágenes, videos, credenciales, evidencias y expedientes según rol, institución, path y metadatos.
- Diferenciar correctamente Cloud Storage Security Rules de Firestore Security Rules y elegir dónde validar cada aspecto de la seguridad.
- Integrar Authentication, Firestore, Custom Claims y Cloud Functions en una arquitectura profesional de protección de archivos.[cite:1][cite:2]
- Construir y justificar el sistema completo de reglas del proyecto oficial del libro con enfoque de mínimo privilegio y separación entre archivos públicos y privados.
Introducción¶
En muchas aplicaciones modernas, la información más sensible no vive solo en la base de datos. También existe en forma de archivos: fotografías, constancias, expedientes, evidencias, firmas digitales, documentos PDF, credenciales visuales, videos y materiales multimedia. Proteger únicamente Firestore pero dejar abierto el almacenamiento es como cerrar la puerta principal y dejar todas las ventanas abiertas.
Cloud Storage para Firebase permite almacenar objetos binarios a escala, pero precisamente por esa flexibilidad requiere un sistema de autorización riguroso. La documentación oficial explica que Firebase Security Rules para Cloud Storage permiten gestionar permisos basados en rutas y validar solicitudes para restringir accesos o limitar características de los archivos, como su tamaño o tipo.[cite:1]
Esto es especialmente importante porque una petición a Storage no es simplemente “leer un documento” o “actualizar un campo”. Aquí se trabaja con objetos completos, paths, tamaños, metadatos y tipos MIME. Por eso, las reglas de Storage tienen una lógica similar a las de Firestore, pero se aplican sobre un recurso distinto y con capacidades diferentes.[cite:1][cite:2]
En este capítulo se explicará cómo funciona el motor de reglas de Cloud Storage, cómo diseñar paths seguros, cómo validar archivos mediante metadatos y cómo integrar Authentication, Firestore y Cloud Functions para construir una arquitectura de almacenamiento segura. Todo se aplicará al proyecto transversal del libro, que necesita proteger fotografías de usuarios, firmas digitales, credenciales, expedientes, evidencias, tareas, PDFs y recursos multimedia con permisos distintos según el rol del usuario.
Desarrollo completo¶
Introducción conceptual¶
¿Qué son las Storage Security Rules?¶
Las Storage Security Rules son reglas declarativas que se ejecutan en los servidores de Firebase y determinan si una operación sobre un archivo en Cloud Storage está permitida o denegada. La documentación oficial las describe como reglas de autorización por archivo y por path, además de mecanismo de validación de datos para nombres, rutas y propiedades del archivo como contentType y size.[cite:1]
¿Por qué son necesarias?¶
Porque un archivo puede contener información muy sensible y, a diferencia de un documento de Firestore, su impacto visual o legal puede ser inmediato. Un PDF con expedientes, una firma digital o una credencial no solo es un dato: puede ser evidencia, identidad o información privada crítica.
Las reglas son necesarias para decidir:
- quién puede leer un archivo;
- quién puede subirlo;
- quién puede reemplazarlo;
- quién puede borrarlo;
- qué tipo de archivo puede subirse;
- cuánto puede pesar;
- en qué carpeta virtual puede vivir;
- qué metadatos debe contener.
Diferencias entre Firestore Rules y Storage Rules¶
Ambas usan el lenguaje de Firebase Security Rules y comparten conceptos como request.auth, match, allow y funciones personalizadas.[cite:1][cite:2] Sin embargo, el recurso evaluado es distinto.
En Firestore, la unidad típica es un documento con campos estructurados. En Storage, la unidad es un objeto binario con path y metadatos. Por eso, Storage pone mucho énfasis en:
- path del archivo;
- tamaño;
contentType;- metadata personalizada;
- separación entre recurso existente y recurso propuesto.
Flujo de autorización para archivos¶
El flujo general es:
- El cliente intenta leer, subir, modificar metadatos o borrar un archivo.
- Cloud Storage identifica el path solicitado.
- Evalúa las reglas
matchque aplican a esa ruta.[cite:1] - Construye el contexto
request, incluyendo autenticación, path, tiempo y el nuevo recurso en caso de escritura.[cite:2] - Evalúa la condición booleana correspondiente.
- Si la condición es verdadera, permite la operación; si es falsa, la deniega.
Funcionamiento interno¶
Motor de evaluación¶
La documentación de condiciones deja claro que el bloque fundamental en Storage Rules es la condición, una expresión booleana que determina si una operación se permite o no.[cite:2]
Toda regla finalmente responde una sola pregunta: ¿la expresión es true? Si no, el acceso se rechaza.
request¶
La documentación oficial enumera varias propiedades del objeto request: auth, params, path, resource y time.[cite:2] En términos prácticos, request representa la solicitud entrante y su contexto de evaluación.
resource¶
resource describe el archivo existente en Cloud Storage, incluyendo propiedades como name, bucket, size, contentType, metadata, timeCreated, updated y hashes del objeto.[cite:2] Es la fotografía del recurso actual.
auth¶
request.auth contiene contexto de autenticación cuando el usuario está autenticado, incluyendo uid y claims del token JWT en request.auth.token; si el usuario no está autenticado, request.auth es null.[cite:1][cite:2]
request.auth¶
Aunque suele hablarse de auth de forma general, en reglas la referencia correcta es request.auth. Es el punto de entrada para autorizaciones por usuario, por rol o por claims personalizados.[cite:1][cite:2]
request.resource¶
En escrituras, la documentación indica que request.resource contiene un subconjunto de los metadatos que se escribirán si la operación es permitida. Puede usarse junto con resource para validar integridad y restricciones de aplicación.[cite:2]
Esto es esencial al controlar:
- tamaño de carga;
- tipo MIME;
- metadata obligatoria;
- cambios permitidos en metadata;
- reemplazo de archivos existentes.
metadata¶
resource.metadata y request.resource.metadata permiten acceder a metadatos personalizados definidos por la aplicación.[cite:2] Esta característica es extremadamente poderosa porque permite reforzar autorización más allá del path. Por ejemplo, un archivo puede contener en metadata el ownerId, institutionId, groupId o visibility.
time¶
request.time representa el tiempo del servidor en el momento de evaluación.[cite:2] Puede usarse para restricciones temporales, como permitir cierta carga solo dentro de una ventana de entrega o bloquear operaciones después de una fecha límite.
Operaciones¶
Storage agrupa operaciones de lectura y escritura, y también permite razonar sobre creación, actualización y borrado aunque el vocabulario práctico más habitual en las reglas sea read y write.
read¶
Autoriza descarga o acceso de lectura al archivo.
write¶
Agrupa operaciones de subida, reemplazo, metadata update y borrado.
create¶
Conceptualmente es una escritura cuando el objeto aún no existe. Es importante distinguirla en el diseño aunque la regla se exprese sobre escritura general, porque muchas veces crear debe tener criterios diferentes a reemplazar o borrar.
update¶
Corresponde al reemplazo del contenido del archivo o de sus metadatos. Aquí resource y request.resource deben compararse para decidir qué cambios se aceptan.
delete¶
Es la eliminación del objeto. Normalmente debería estar más restringida que la mera lectura.
Validaciones¶
Usuario autenticado¶
El patrón básico documentado por Firebase es:
Esto exige autenticación para cualquier operación sobre un path dado.[cite:1]
Propietario del archivo¶
La documentación también muestra el patrón de archivos privados por usuario usando prefijos que contienen el UID, por ejemplo /users/{userId}/profilePicture.png, autorizando escritura solo si request.auth.uid == userId.[cite:2]
Roles¶
Los roles pueden venir en request.auth.token, por ejemplo:
superadminadmindirectorteacherstudentparentguest
Restricción por institución¶
En aplicaciones multiempresa o multiinstitución, el path o la metadata deben incluir el identificador organizacional. De lo contrario, la autorización se vuelve mucho más frágil.
Restricción por carpeta¶
Storage trabaja sobre paths, por lo que la estructura de carpetas virtuales es parte del modelo de seguridad. Una carpeta mal diseñada equivale a una regla más difícil de escribir y de auditar.
Restricción por extensión¶
La documentación muestra que es posible restringir nombres con expresiones regulares, por ejemplo permitiendo solo archivos .txt mediante imageId.matches(".*\\.txt").[cite:2] Esto demuestra que el nombre del objeto también forma parte de la superficie de validación.
Restricción por tipo MIME¶
Firebase documenta el uso de request.resource.contentType.matches('image/.*') para permitir solo imágenes.[cite:1][cite:2]
Restricción por tamaño¶
También se documenta explícitamente la validación de request.resource.size < 5 * 1024 * 1024 para limitar un upload a menos de 5 MB.[cite:1][cite:2]
Restricción por nombre de archivo¶
Además de extensiones, puede exigirse una convención segura de nombres para impedir caracteres extraños, prefijos indebidos o formatos no controlados.
Restricción por metadatos¶
Los metadatos personalizados permiten añadir una segunda capa de control. Por ejemplo, exigir que todo expediente PDF lleve:
ownerIdinstitutionIddocumentTypevisibility
Organización¶
Protección por carpetas virtuales¶
En Cloud Storage no existen carpetas reales como sistema jerárquico tradicional; existen nombres de objeto con prefijos. Aun así, la organización por carpetas virtuales es fundamental porque las reglas hacen match sobre esos paths.[cite:1]
Ejemplo:
/public//users/{uid}/profile//institutions/{institutionId}/credentials//institutions/{institutionId}/evidences//institutions/{institutionId}/expedientes/
Protección por usuarios¶
Es ideal para recursos estrictamente privados o personales, como fotografías de perfil, firma personal o archivos de un alumno concreto.
Protección por módulos¶
También es útil organizar por dominio funcional:
profilescredentialsevidencesdocumentsmultimedia
Protección para aplicaciones multiempresa¶
En aplicaciones multiempresa, cada path sensible debería contener explícitamente el institutionId o tenantId. Esto simplifica reglas, auditoría y aislamiento organizacional.
Integración¶
Authentication¶
Storage Security Rules se integra directamente con Firebase Authentication. La documentación oficial indica que request.auth se llena con el uid y claims del usuario autenticado, y es null si no existe autenticación.[cite:1][cite:2]
Firestore¶
La documentación de condiciones explica que las reglas de Storage pueden usar firestore.get() y firestore.exists() para evaluar autorización contra documentos de Cloud Firestore.[cite:2] Esto permite, por ejemplo, leer membresías, relaciones de amistad, grupos o permisos institucionales antes de permitir acceso a un archivo.
Custom Claims¶
Como los claims viajan en request.auth.token, son ideales para roles relativamente estables, como superadmin, director o teacher.[cite:2]
Cloud Functions¶
Cloud Functions complementa las reglas cuando se necesita lógica privilegiada. Por ejemplo:
- generar una credencial PDF;
- mover archivos entre zonas seguras;
- firmar metadata de confianza;
- limpiar archivos temporales;
- crear URLs de acceso controlado.
Optimización¶
Rendimiento¶
La optimización de reglas en Storage no consiste solo en escribir menos líneas, sino en diseñar paths y metadatos que permitan decidir rápido y con pocas dependencias externas. Cuando una regla necesita consultar Firestore, aumenta complejidad operacional y dependencia entre servicios.[cite:2]
Organización de reglas¶
Un archivo profesional debe agruparse por zonas del bucket y reutilizar funciones. No conviene repetir veinte veces el mismo criterio de autenticación, rol o institución.
Reutilización mediante funciones¶
La documentación oficial indica que las reglas soportan funciones personalizadas y que estas mejoran mantenibilidad a medida que crece la complejidad del ruleset.[cite:2]
Pruebas¶
Firebase recomienda integrar desarrollo, pruebas y despliegue de reglas como parte del flujo profesional. Las reglas no deben publicarse “por intuición”. Deben probarse con escenarios reales de lectura, subida, reemplazo y borrado.[cite:2]
Depuración¶
La depuración exige saber si falló:
- autenticación;
- path;
- claim;
- metadata;
- tipo MIME;
- tamaño;
- lectura auxiliar a Firestore.
Ejemplos paso a paso¶
Ejemplo 1: carpeta privada autenticada¶
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /internal/{fileName} {
allow read, write: if request.auth != null;
}
}
}
Este patrón está alineado con la documentación cuando exige autenticación para acceso privado.[cite:1][cite:2]
Ejemplo 2: fotografía de perfil por usuario¶
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /users/{userId}/profilePicture.png {
allow read;
allow write: if request.auth != null && request.auth.uid == userId;
}
}
}
Firebase muestra este caso como ejemplo de “user private”, donde el path contiene el identificador del usuario.[cite:2]
Ejemplo 3: validar imágenes de hasta 5 MB¶
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /images/{imageId} {
allow write: if request.resource.size < 5 * 1024 * 1024
&& request.resource.contentType.matches('image/.*');
}
}
}
Este ejemplo proviene directamente de la documentación oficial.[cite:1][cite:2]
Ejemplo 4: acceso de grupo con metadata¶
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /files/{groupId}/{fileName} {
allow read: if request.auth != null
&& resource.metadata.owner == request.auth.token.groupId;
allow write: if request.auth != null
&& request.auth.token.groupId == groupId;
}
}
}
Este patrón también está documentado por Firebase para escenarios de grupo privado usando claims y metadata.[cite:2]
Ejemplo 5: autorización apoyada en Firestore¶
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /users/{userId}/photos/{fileId} {
allow read: if request.auth != null &&
firestore.exists(/databases/(default)/documents/users/$(userId)/friends/$(request.auth.uid));
}
}
}
La documentación muestra este patrón para permitir que solo amigos vean las fotos de un usuario, usando firestore.exists().[cite:2]
Proyecto transversal: arquitectura de seguridad de Storage¶
El proyecto oficial del libro requiere proteger múltiples tipos de archivo con criterios distintos.
Roles del sistema¶
superadminadmindirectorteacherstudentparentguest
Principios arquitectónicos¶
- Todo archivo sensible vive dentro de un path con
institutionId. - Todo archivo personal vive además dentro de un path con
uido actor principal. - Los recursos públicos se separan estrictamente de los privados.
- Las URLs no sustituyen reglas; el control principal vive en Security Rules.
- Los archivos críticos no se crean ni actualizan libremente desde cliente si pueden afectar integridad institucional.
Estructura de carpetas propuesta¶
/public/
/institutions/{institutionId}/profiles/{userId}/photo.jpg
/institutions/{institutionId}/signatures/{userId}/signature.png
/institutions/{institutionId}/credentials/{userId}/{credentialId}.pdf
/institutions/{institutionId}/records/{studentId}/{fileName}
/institutions/{institutionId}/evidences/{groupId}/{studentId}/{fileName}
/institutions/{institutionId}/tasks/{taskId}/{fileName}
/institutions/{institutionId}/documents/admin/{fileName}
/institutions/{institutionId}/media/{module}/{fileName}
Funciones reutilizables¶
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
function isSignedIn() {
return request.auth != null;
}
function uid() {
return request.auth.uid;
}
function role() {
return request.auth.token.role;
}
function institution() {
return request.auth.token.institutionId;
}
function sameInstitution(institutionId) {
return isSignedIn() && institution() == institutionId;
}
function isSuperAdmin() {
return isSignedIn() && request.auth.token.superadmin == true;
}
function isAdmin(institutionId) {
return sameInstitution(institutionId) && (role() == 'admin' || role() == 'director');
}
function isTeacher(institutionId) {
return sameInstitution(institutionId) && role() == 'teacher';
}
function isStudent(institutionId) {
return sameInstitution(institutionId) && role() == 'student';
}
function isParent(institutionId) {
return sameInstitution(institutionId) && role() == 'parent';
}
Fotografías de usuarios¶
match /institutions/{institutionId}/profiles/{userId}/{fileName} {
allow read: if sameInstitution(institutionId) || isSuperAdmin();
allow write: if (uid() == userId && sameInstitution(institutionId))
|| isAdmin(institutionId)
|| isSuperAdmin();
}
Justificación: las fotos pueden ser visibles internamente dentro de la institución, pero solo el propio usuario o un rol administrativo deben poder reemplazarlas.
Firmas digitales¶
match /institutions/{institutionId}/signatures/{userId}/{fileName} {
allow read: if uid() == userId || isAdmin(institutionId) || isSuperAdmin();
allow write: if uid() == userId || isSuperAdmin();
}
Las firmas tienen sensibilidad alta. No conviene abrir lectura general dentro de la institución.
Credenciales¶
match /institutions/{institutionId}/credentials/{userId}/{credentialId} {
allow read: if uid() == userId || isAdmin(institutionId) || isSuperAdmin();
allow write: if false;
}
Justificación: las credenciales digitales deben emitirse desde Cloud Functions con permisos privilegiados, no desde clientes.
Expedientes¶
match /institutions/{institutionId}/records/{studentId}/{fileName} {
allow read: if uid() == studentId
|| isAdmin(institutionId)
|| isTeacher(institutionId)
|| isSuperAdmin();
allow write: if isAdmin(institutionId) || isSuperAdmin();
}
Evidencias escolares¶
match /institutions/{institutionId}/evidences/{groupId}/{studentId}/{fileName} {
allow read: if uid() == studentId
|| isTeacher(institutionId)
|| isAdmin(institutionId)
|| isSuperAdmin();
allow write: if uid() == studentId
&& isStudent(institutionId)
&& request.resource.size < 20 * 1024 * 1024
&& (
request.resource.contentType.matches('image/.*')
|| request.resource.contentType.matches('application/pdf')
);
}
Tareas¶
match /institutions/{institutionId}/tasks/{taskId}/{fileName} {
allow read: if sameInstitution(institutionId) || isSuperAdmin();
allow write: if isTeacher(institutionId) || isAdmin(institutionId) || isSuperAdmin();
}
Documentos administrativos PDF¶
match /institutions/{institutionId}/documents/admin/{fileName} {
allow read: if isAdmin(institutionId) || isSuperAdmin();
allow write: if isAdmin(institutionId)
&& request.resource.contentType.matches('application/pdf')
&& request.resource.size < 10 * 1024 * 1024
|| isSuperAdmin();
}
Recursos multimedia¶
match /institutions/{institutionId}/media/{module}/{fileName} {
allow read: if sameInstitution(institutionId) || isSuperAdmin();
allow write: if isTeacher(institutionId)
|| isAdmin(institutionId)
|| isSuperAdmin();
}
}
}
Casos reales¶
Fotografías de perfil¶
Las fotografías de perfil suelen necesitar un modelo mixto: escritura privada y lectura más amplia dentro del ecosistema, según el caso de negocio. No se debe asumir que porque “es solo una foto” no requiere protección. Puede contener información personal identificable.
Evidencias escolares¶
Son archivos típicamente subidos por alumnos y revisados por docentes. Deben restringirse por rol, institución, tamaño y tipo MIME. Además, conviene impedir que otro alumno acceda a evidencias ajenas.
Credenciales digitales¶
La credencial es un documento institucional de confianza. Por esa razón, la arquitectura recomendada es lectura autorizada y generación controlada desde backend.
Expedientes¶
Los expedientes suelen ser el caso más sensible de todo el bucket. Deben tratarse como almacenamiento privado y altamente regulado.
Recursos multimedia¶
Estos pueden requerir permisos más flexibles, pero no necesariamente públicos. Un video formativo interno o material docente no debe confundirse con un recurso abierto a internet.
Documentos administrativos¶
PDFs administrativos, actas o constancias requieren un control mucho más cercano al de expedientes que al de material multimedia.
Comparaciones técnicas¶
Firestore Rules vs Storage Rules¶
| Criterio | Firestore Rules | Storage Rules |
|---|---|---|
| Unidad protegida | Documento | Archivo/objeto |
| Datos evaluados | Campos estructurados | Path, metadata, tamaño, tipo MIME |
| Contexto principal | resource.data [cite:2] |
resource y request.resource [cite:2] |
| Uso típico | acceso a datos | acceso a binarios |
Archivo público vs archivo privado¶
| Criterio | Público | Privado |
|---|---|---|
| Requiere autenticación | No necesariamente [cite:2] | Sí, normalmente [cite:1][cite:2] |
| Casos de uso | assets, contenido abierto | fotos, expedientes, evidencias |
| Riesgo | menor si está bien clasificado | alto si se expone |
| Diseño recomendado | separar en zona dedicada | reglas de mínimo privilegio |
Path-based vs metadata-based¶
| Criterio | Path-based | Metadata-based |
|---|---|---|
| Simplicidad | Alta | Media |
| Trazabilidad | Alta | Alta |
| Flexibilidad | Media | Alta |
| Uso ideal | usuario/institución visibles en ruta | permisos complementarios, visibilidad, tipo de recurso |
Claim vs consulta a Firestore¶
| Criterio | Custom Claim | firestore.get() / firestore.exists() |
|---|---|---|
| Velocidad conceptual | Más simple | Más flexible |
| Dependencia externa | No | Sí [cite:2] |
| Escenario ideal | roles estables | membresías, relaciones dinámicas |
| Complejidad operativa | Menor | Mayor |
Buenas prácticas¶
- Aplicar el principio de mínimo privilegio en cada zona del bucket.
- Separar físicamente los archivos públicos de los privados mediante paths claros.
- Diseñar rutas que incluyan información suficiente para autorizar correctamente, como
institutionIdyuserId. - Validar tamaño y
contentTypeen uploads, no confiar solo en el cliente.[cite:1][cite:2] - Usar metadata personalizada cuando el negocio lo justifique, pero sin depender de ella como único control cuando el path ya puede expresar el dominio.
- Reservar escrituras de archivos críticos, como credenciales o documentos oficiales, para Cloud Functions privilegiadas.
- Mantener funciones reutilizables para roles, autenticación e institución.[cite:2]
- Usar Firestore en reglas solo cuando realmente aporte valor y justificación arquitectónica.[cite:2]
- Gestionar URLs con cuidado: una URL de acceso no debe convertirse en un sustituto informal de la autorización.
- Versionar y desplegar reglas como parte del proyecto, no como cambios manuales aislados.
Errores comunes¶
- Pensar que conocer la URL del archivo equivale a tener permiso legítimo.
- Mezclar archivos públicos y privados en la misma zona lógica del bucket.
- Permitir
writeamplio solo porque “el cliente ya valida”. - No validar
contentTypeni tamaño.[cite:1][cite:2] - Basar toda la seguridad en el nombre del archivo sin considerar rol o institución.
- No incluir
institutionIden paths multiempresa. - Permitir reemplazo de archivos críticos por parte del usuario sin restricciones.
- No limitar lectura de firmas digitales o expedientes.
- Abusar de lecturas a Firestore desde reglas sin una estrategia clara.[cite:2]
- Diseñar reglas diferentes para Storage y Firestore que terminan contradiciéndose en el mismo flujo de negocio.
Checklist para producción¶
Antes de publicar Storage en producción, revisar:
- ¿El ruleset usa
rules_version = '2';? - ¿Existen zonas públicas claramente separadas de las privadas?
- ¿Los archivos sensibles exigen autenticación?
- ¿Las rutas incluyen
institutionId,userIdu otra información necesaria para autorizar correctamente? - ¿Los uploads validan tamaño y tipo MIME?[cite:1][cite:2]
- ¿Los archivos críticos solo pueden crearse o modificarse desde backend privilegiado?
- ¿Las reglas reflejan realmente los roles del negocio?
- ¿Las firmas, credenciales y expedientes tienen protección reforzada?
- ¿El uso de
firestore.get()ofirestore.exists()está justificado?[cite:2] - ¿Se probaron operaciones de lectura, subida, reemplazo y borrado para cada rol?
- ¿Las URLs y descargas no están sustituyendo el modelo formal de autorización?
Resumen¶
Las Cloud Storage Security Rules son la capa que protege archivos en Firebase mediante autorización por ruta y validación de solicitudes. La documentación oficial destaca que permiten restringir accesos por usuario o por path y también validar características como tamaño, nombre, contentType y metadata del archivo.[cite:1][cite:2]
Su motor de evaluación trabaja con varios elementos clave: request.auth aporta identidad y claims del usuario autenticado, resource representa el objeto ya existente y request.resource describe el nuevo recurso propuesto durante escrituras, incluyendo metadatos relevantes.[cite:1][cite:2] A partir de esos elementos, las reglas pueden autorizar o denegar lecturas, subidas, reemplazos y borrados.
En aplicaciones reales, la seguridad de Storage depende tanto de las reglas como del diseño de paths. Un bucket bien organizado separa archivos públicos y privados, incorpora institutionId y userId cuando corresponde, y reserva los archivos de alta confianza —como credenciales, firmas o expedientes— para flujos controlados por backend. Además, cuando el negocio lo exige, Storage puede integrarse con Firestore mediante firestore.get() y firestore.exists() para aplicar criterios adicionales de autorización.[cite:2]
En el proyecto oficial del libro, esta arquitectura permite proteger fotografías, firmas digitales, credenciales, expedientes, evidencias, tareas, PDFs y multimedia con permisos distintos para superadministrador, administrador, director, docente, alumno, padre de familia e invitado. Ese es el objetivo profesional del capítulo: convertir el almacenamiento de archivos en una capa segura, mantenible y coherente con el resto de la arquitectura Firebase.
Conceptos clave¶
- Cloud Storage Security Rules.[cite:1]
- Autorización path-based.[cite:1]
request.auth.[cite:1][cite:2]request.resource.[cite:2]resource.[cite:2]resource.metadata.[cite:2]request.resource.contentType.[cite:1][cite:2]request.resource.size.[cite:1][cite:2]- MIME type.
- Carpeta virtual.
- Metadata personalizada.[cite:2]
firestore.get().[cite:2]firestore.exists().[cite:2]- Custom Claims.[cite:2]
- Mínimo privilegio.
Preguntas de repaso¶
- ¿Qué son las Cloud Storage Security Rules y qué problema resuelven?[cite:1]
- ¿Qué diferencias principales existen entre Firestore Rules y Storage Rules?[cite:1][cite:2]
- ¿Qué información aporta
request.authdurante la evaluación de una regla?[cite:1][cite:2] - ¿Qué diferencia existe entre
resourceyrequest.resource?[cite:2] - ¿Por qué conviene validar
contentTypey tamaño de archivo en reglas?[cite:1][cite:2] - ¿Qué ventajas ofrece incluir
institutionIdyuserIden el path del archivo? - ¿Cuándo conviene usar metadata personalizada para reforzar autorización?[cite:2]
- ¿Qué ventajas y riesgos tiene integrar Storage Rules con Firestore mediante
firestore.get()ofirestore.exists()?[cite:2] - ¿Por qué la creación de credenciales y expedientes sensibles debería delegarse a Cloud Functions?
- ¿Qué zonas del bucket del proyecto oficial deberían ser públicas y cuáles privadas?
Ejercicios prácticos¶
- Diseña una estructura de paths para separar archivos públicos, privados y multiinstitución.
- Escribe una regla para que cada usuario solo pueda subir su propia foto de perfil.[cite:2]
- Crea una regla que permita solo imágenes menores a 5 MB y documentos PDF menores a 10 MB.[cite:1][cite:2]
- Implementa protección para expedientes estudiantiles con acceso restringido por institución y rol.
- Diseña reglas para evidencias escolares que permitan upload al alumno y lectura al docente.
- Crea una estrategia de metadatos personalizados para
ownerId,institutionIdydocumentType. - Implementa una regla que consulte Firestore para validar membresía antes de permitir lectura de un recurso compartido.[cite:2]
- Diseña el ruleset para firmas digitales con lectura muy restringida.
- Propón un flujo donde Cloud Functions genere credenciales PDF y Storage Rules impida al cliente reemplazarlas.
- Elabora una auditoría de seguridad de un bucket que hoy usa
allow read, write: if request.auth != null;en toda su estructura.
Bibliografía y referencias oficiales¶
- Understand Firebase Security Rules for Cloud Storage: https://firebase.google.com/docs/storage/security [cite:1]
- Use conditions in Firebase Cloud Storage Security Rules: https://firebase.google.com/docs/storage/security/rules-conditions [cite:2]