Sistema de Permisos y Roles para Apps Web a Medida
Cómo diseñar un sistema de permisos y roles granulares para tu aplicación web a medida
Llega un momento en la vida de toda aplicación web a medida en el que alguien se da cuenta de que el comercial lleva tres meses viendo los datos financieros del departamento de dirección. O que un manager no puede aprobar las solicitudes de su propio equipo. O peor: un administrador borra registros de producción porque su rol tenía permisos que nadie se paró a revisar.
He visto los tres escenarios. Los tres comparten la misma raíz: un sistema de permisos que se diseñó deprisa, se heredó de otro proyecto, o directamente no existe.
Y el problema no es solo operativo. Según el informe de IBM sobre el coste de las brechas de datos en 2025, el 16 % de las brechas involucran credenciales comprometidas con permisos excesivos. El principio de mínimo privilegio no es una sugerencia bienintencionada que se lee en un libro de texto. Es la diferencia entre que una cuenta comprometida pueda leer un par de tablas o pueda tumbar toda tu base de datos.
RBAC, ABAC y ReBAC: qué modelo elegir y por qué
Lo primero: no abras el editor. Antes de tocar una línea de código, siéntate con el equipo y entiende qué modelo de control de acceso encaja con vuestra realidad.
RBAC (Role-Based Access Control) sigue siendo el caballo de batalla. Creas roles —administrador, editor, viewer—, les asignas permisos, y vinculas usuarios a roles. Piensa en ello como en las llaves de un edificio de oficinas: cada llave abre un conjunto fijo de puertas. Es fácil de implementar, fácil de explicar al cliente y fácil de auditar. Pero tiene un límite claro: cuando necesitas reglas del tipo "un manager solo puede ver los datos de su departamento, no los de otros", RBAC puro se queda corto.
ABAC (Attribute-Based Access Control) añade contexto. Evalúa permisos en función de atributos del usuario, del recurso y del entorno. Con ABAC puedes expresar cosas como "un usuario con rol editor puede publicar artículos solo si el artículo pertenece a su sección y es horario laboral". Es una navaja suiza, pero cuidado: cuantos más atributos combinas, más difícil es responder a la pregunta "¿por qué este usuario puede hacer esto?". Y si no puedes responder a esa pregunta rápido, tu auditoría tiene un agujero.
ReBAC (Relationship-Based Access Control) define permisos a través de las relaciones entre entidades. "El usuario A puede editar el documento B porque es miembro del equipo C que es propietario del proyecto D que contiene el documento B." Si te suena complejo, lo es. Pero también es el modelo que Google eligió internamente con Zanzibar para gestionar permisos en Google Drive, Docs y otros productos. Hoy, implementaciones open source como OpenFGA o SpiceDB lo hacen accesible para proyectos de cualquier escala.
Mi recomendación para la mayoría de aplicaciones web a medida en el mercado español: arranca con RBAC con extensiones. Incorpora ABAC cuando aparezcan reglas contextuales que RBAC no pueda cubrir. Y reserva ReBAC para proyectos donde las relaciones entre entidades son el eje central de la lógica de negocio.
Cómo estructurar el modelo de datos
Un modelo de datos sólido para RBAC granular se apoya en cuatro piezas. Ninguna es opcional si quieres que el sistema escale.
Permisos. Cada permiso es una acción sobre un recurso concreto. Utiliza la convención recurso:acción y mantenla sin excepciones: facturas:crear, facturas:leer, facturas:editar, facturas:eliminar, usuarios:gestionar. Huye de permisos comodín tipo admin:todo. Un permiso que lo permite todo es un permiso que no puedes auditar, y un permiso que no puedes auditar es una bomba de relojería.
Roles. Un rol agrupa permisos que corresponden a una función real del negocio. Diseña roles basándote en lo que la gente hace de verdad, no en niveles jerárquicos inventados. "Gestor de pedidos" te dice algo útil sobre lo que puede hacer esa persona. "Nivel 3" no te dice absolutamente nada.
Asignación usuario-rol. Puede ser global (el usuario tiene el rol en todo el sistema) o contextualizada (el usuario tiene el rol solo en un proyecto, un departamento o una sucursal). Esta contextualización es exactamente lo que transforma un RBAC de manual en un sistema realmente granular. Sin ella, estás dando llaves maestras cuando la gente solo necesita entrar a su planta.
Jerarquía de roles (opcional). Permite que un rol herede los permisos de otro. El "Manager" hereda todo lo del "Editor" más sus propios permisos. Simplifica la gestión del día a día, pero complica el debugging: cuando un usuario tiene un permiso que no debería tener, necesitas recorrer toda la cadena de herencia para encontrar de dónde viene. Úsala con moderación y documenta cada relación de herencia.
Patrones técnicos que realmente funcionan en producción
La implementación del sistema de permisos no es un módulo aislado. Toca cada capa de tu arquitectura. Estos son los patrones que, después de muchos proyectos, me han dado mejores resultados:
Middleware de autorización centralizado. Toda verificación de permisos pasa por un punto central. Nunca dispersa en cada controlador o servicio. Frameworks como Express.js con middleware propio, Django con su sistema de permissions o Spring Security facilitan este enfoque.
// Pseudocódigo del middleware
function authorize(requiredPermission) {
return function(request, response, next) {
const userPermissions = getPermissionsForUser(request.user, request.context)
if (userPermissions.includes(requiredPermission)) {
return next()
}
return response.forbidden()
}
}
Ese getPermissionsForUser esconde toda la complejidad del modelo —roles, herencia, scopes— detrás de una interfaz limpia. El controlador solo necesita saber qué permiso exigir.
La autorización vive en el servidor. Siempre. El frontend puede ocultar botones para mejorar la experiencia, pero la verificación real ocurre en la API. Cualquier restricción solo en el frontend es una puerta sin cerradura.
Cache de permisos con invalidación inteligente. Evaluar permisos contra la base de datos en cada petición es un cuello de botella. Cachea en Redis o cache local con un TTL de 5-15 minutos e invalida inmediatamente cuando cambian los roles de ese usuario.
Registro de auditoría completo. Cada verificación denegada y cada cambio en roles queda registrado. Es lo que usarás para debuggear accesos, para auditorías de seguridad y para demostrar cumplimiento normativo.
Permisos a nivel de recurso: donde se juega la partida de verdad
Saber que un usuario "puede editar artículos" no es suficiente. La pregunta que importa es: ¿qué artículos? Un editor con acceso a todos los artículos de la plataforma tiene permisos de acción correctos pero un alcance desmedido. Es como darle a alguien la llave de todas las taquillas del gimnasio cuando solo necesita la suya.
Hay tres mecanismos para resolver esto:
Filtros en las consultas de base de datos. Cuando un usuario pide una lista de recursos, la consulta ya incluye un filtro por los recursos a los que tiene acceso. No cargas todo y filtras después en la aplicación. La base de datos devuelve solo lo que ese usuario puede ver. Esto además escala mucho mejor porque el trabajo pesado lo hace el motor de base de datos, no tu capa de aplicación.
Verificación de propiedad. Para operaciones sobre un recurso concreto, verificas la relación del usuario con ese recurso: ¿es el creador? ¿Pertenece al equipo propietario? ¿Tiene un permiso explícito?
Políticas de alcance (scopes). Defines contextos que limitan dónde aplican los permisos. Un usuario puede ser "Manager" pero solo en el scope "Departamento de Marketing". Tu modelo de datos necesita reflejar esa triple relación: usuario-rol-scope.
Panel de administración: que no sea territorio exclusivo de ingeniería
Un sistema de permisos que solo el desarrollador puede gestionar tiene un cuello de botella operativo. Cada cambio requiere un ticket, un despliegue y una persona técnica disponible.
Tu panel de administración de permisos necesita, como mínimo:
- Gestión de roles: crear, editar y eliminar roles con una interfaz clara —checkboxes o drag-and-drop— para asignar permisos a cada rol
- Asignación de usuarios a roles: buscador de usuarios, vista de sus roles actuales, capacidad de asignar o revocar con efecto inmediato
- Vista de permisos efectivos: dado un usuario concreto, muestra todos sus permisos y de qué rol o asignación proviene cada uno. Esta vista es la que más vas a agradecer cuando lleguen los tickets de "no tengo acceso a X"
- Historial de cambios: quién modificó qué rol o permiso, cuándo y con qué justificación
El acceso a este panel debe estar restringido a superadministradores. Cada acción requiere confirmación y queda registrada en el log de auditoría. Sin excepciones.
Errores que he visto repetirse (y cómo esquivarlos)
Hardcodear roles en el código. Si tu codebase tiene if (user.role === 'admin') repartido por veinte archivos, cada cambio en la estructura de roles exige modificar código, pasar tests y redesplegar. Los roles y permisos son datos, no constantes. Trátalos como tales.
Olvidar la revocación. Tan crítico es poder dar permisos como quitarlos. Cuando un empleado cambia de departamento o se va, sus accesos tienen que revocarse en segundos. No en días.
Diseñar solo para hoy. Tu aplicación tiene ahora tres roles y 20 permisos. En dos años tendrás quince roles y 200 permisos. Si tu modelo no soporta esa escala, acabarás rediseñándolo bajo presión.
Asumir que todo está permitido salvo lo prohibido. El enfoque correcto es deny-by-default: todo lo que no está explícitamente permitido está prohibido. Me sigue sorprendiendo la cantidad de aplicaciones que arrancan con permisos amplios y luego restringen caso por caso. Ese camino siempre deja grietas.
Marco legal: los permisos granulares no son opcionales
El RGPD y la LOPDGDD en España exigen que el acceso a datos personales esté limitado a las personas que necesitan ese acceso para desempeñar su función. Un sistema de permisos granular no es solo buena ingeniería. Es un requisito legal. La AEPD puede sancionar a empresas que no limitan adecuadamente el acceso interno a datos personales, y las multas no son simbólicas.
Documenta tu modelo de permisos como parte del registro de actividades de tratamiento. Deja claro qué roles acceden a qué categorías de datos personales y cuál es la justificación de cada acceso. Esa documentación es tu mejor defensa ante una inspección.
Lo que separa un sistema de permisos robusto de uno que da problemas
Diseñar un buen sistema de permisos no es un problema de complejidad técnica extrema. Es un problema de disciplina: modelo de datos limpio, autorización centralizada, deny-by-default, auditoría completa y un panel de administración que permita a personas no técnicas gestionar el día a día. Si fallas en cualquiera de esas piezas, el sistema se degrada con cada usuario nuevo y cada rol adicional.
Si estás construyendo una aplicación web a medida y necesitas un sistema de permisos que sea seguro, que escale y que cumpla con la normativa española y europea, en Tangram Consulting llevamos años implementando modelos RBAC y ABAC en proyectos de todos los tamaños. Hablemos de tu proyecto y diseñamos juntos la arquitectura de permisos que necesita.