El control de acceso basado en roles es un modelo de autorización donde los permisos se asignan a roles y los usuarios solo los reciben a través de sus roles. La indirección es la idea entera: nada se concede jamás a una persona directamente, así que el cambio organizacional se vuelve cambio de datos — una promoción es una reasignación de rol, no una excavación arqueológica entre grants dispersos. Propuesto por Ferraiolo y Kuhn en 1992 como alternativa a los modelos discrecional y mandatorio más antiguos, se convirtió en el estándar ANSI/INCITS 359 y en el vocabulario de autorización por defecto del software empresarial.
Puntos clave
| Pregunta | Respuesta |
|---|---|
| La indirección | Usuario → rol → permiso — nunca usuario → permiso directo |
| Rol ≠ grupo | Un grupo reúne usuarios; un rol reúne permisos |
| Los niveles del modelo | Core · jerárquico (herencia) · restringido (separación de funciones) |
| El modo de falla | Explosión de roles — atributos codificados como roles hasta que los roles superan a los usuarios |
| La composición | Roles dentro de entradas de ACL: RBAC para la masa, ACLs para las excepciones |
Usuarios, roles, permisos — la indirección en acción
Permisos Roles Usuarios
───────────── ───────────── ─────────────
posts:read ─┐
posts:write ├──▶ Editor ◀────── Ada, Grace
posts:publish ─┘
users:manage ─┐
billing:view ├──▶ Admin ◀────── Linus
posts:* ─┘
posts:read ────▶ Viewer ◀────── todos los demás
Ada publica porque Editor lleva posts:publish — reasigna su rol,
y cada permiso que llevaba se mueve con él. Una edición, no N.
Roles como datos vivos, cableados a los permisos de los objetos:
// JavaScript / Node.js — Back4app JS SDK
// Roles as data: create a role, add members, grant through it
const roleACL = new Parse.ACL();
roleACL.setPublicReadAccess(true);
const editors = new Parse.Role('Editors', roleACL);
editors.getUsers().add(adaUser);
await editors.save();
// Grant by role, not by user — membership changes in one place
const post = new Parse.Object('Post');
const acl = new Parse.ACL(currentUser); // owner entry
acl.setRoleWriteAccess('Editors', true); // RBAC meets the object's ACL
post.setACL(acl);
await post.save(); // Flutter / Dart — Back4app Flutter SDK
// Roles as data: create a role, add members, grant through it
final roleACL = ParseACL()..setPublicReadAccess(allowed: true);
final editors = ParseObject('_Role')
..set('name', 'Editors')
..setACL(roleACL)
..addRelation('users', [adaUser]);
await editors.save();
// Grant by role, not by user — membership changes in one place
final post = ParseObject('Post');
final acl = ParseACL(owner: currentUser) // owner entry
..setRoleWriteAccess('Editors', true); // RBAC meets the object's ACL
post.setACL(acl);
await post.save(); // iOS / Swift — Back4app Swift SDK
// Roles as data: create a role, add members, grant through it
var editors = try ParseRole(name: "Editors")
let savedRole = try await editors.save()
try await savedRole.users.add([adaUser]).save() // membership = a relation
// Grant by role, not by user — membership changes in one place
var post = Post()
var acl = ParseACL()
acl.setReadAccess(user: currentUser, value: true)
acl.setWriteAccess(user: currentUser, value: true) // owner entry
acl.setWriteAccess(roleName: "Editors", value: true) // RBAC meets the ACL
post.ACL = acl
try await post.save() // Android / Kotlin — Back4app Android SDK
// Roles as data: create a role, add members, grant through it
val roleACL = ParseACL()
roleACL.publicReadAccess = true
val editors = ParseRole("Editors", roleACL)
editors.users.add(adaUser)
editors.save()
// Grant by role, not by user — membership changes in one place
val post = ParseObject("Post")
val acl = ParseACL(ParseUser.getCurrentUser()) // owner entry
acl.setRoleWriteAccess("Editors", true) // RBAC meets the object's ACL
post.acl = acl
post.save() El modelo NIST, con precisión
La mayoría de los explicadores comprime el estándar en un listado; la estructura real merece treinta segundos. El RBAC core define usuarios, roles, permisos — y sesiones, el elemento olvidado: un usuario activa un subconjunto de sus roles por sesión, y así es como un admin navega con poderes de miembro por defecto y escala deliberadamente. Las tres reglas del artículo original lo amarran todo: actuar solo a través de un rol, tener solo roles autorizados, hacer solo lo que el rol activo permite. El RBAC jerárquico agrega herencia — los roles senior subsumen a los junior (Gerente ⊇ Empleado), eliminando duplicación. El RBAC restringido agrega separación de funciones: las reglas estáticas prohíben de plano las asignaciones de roles en conflicto (nunca creador-de-pagos y aprobador-de-pagos juntos); las dinámicas permiten la asignación, pero prohíben activar ambos en una misma sesión. Y la aclaración más afilada del NIST, rutinariamente tergiversada: un grupo es una colección de usuarios; un rol es una colección de permisos — el rol se define por lo que puede hacer, no por quién está en él.
RBAC vs. ACL vs. ABAC
| RBAC | ACL | ABAC | |
|---|---|---|---|
| Los permisos se asignan a | Roles | Cada objeto | Reglas de atributos |
| Pregunta nativa | ¿Qué puede hacer esta función? | ¿Quién puede tocar este objeto? | ¿Se permite esto en contexto? |
| Administración | Un lugar por rol | Por objeto | Por política |
| Compartición por objeto | No puede expresarla | Su juego de local | Expresable, verbosa |
| Auditar “¿qué puede hacer Ada?” | Lee sus roles | Recorre todos los objetos | Evalúa todas las reglas |
| Modo de falla | Explosión de roles | Proliferación de listas | Políticas opacas |
La idea que la SERP de los vendedores entierra: estos modelos se componen, no compiten. Los roles manejan el acceso que sigue la función; las entradas de ACL manejan las excepciones por objeto — y la bisagra es la ACE de rol, una línea de la ACL que nombra un role en lugar de un usuario, dando control a nivel de objeto con membresía en un solo lugar. Las condiciones de atributos se apilan encima cuando el contexto (hora, tenant, estado del registro) realmente decide. “¿Cuál de los dos?” suele ser la pregunta equivocada; “¿qué capa maneja qué decisión?” es el diseño.
Explosión de roles — el modo de falla
La enfermedad característica de RBAC: cada excepción acuña un rol, y luego cada proyecto, región y tenant los multiplica — Gerente-Proyecto-A-Region-Oeste-SoloLectura — hasta que los roles superan en número a los usuarios y la respuesta de la auditoría a “¿quién puede hacer qué?” es “nadie sabe”. La causa raíz es siempre la misma: atributos contextuales codificados como roles. Las mitigaciones, en orden: mantén los atributos fuera de los nombres de rol (región y tenant son condiciones o alcances, no roles); maneja la compartición por objeto con entradas de ACL, nunca con roles por objeto; acota los roles por tenant de forma estructural y no con malabares de nombres; y audita — los roles que nadie tiene, los permisos que ningún rol usa y los grants que nadie recuerda son deriva, y la deriva es cómo el privilegio mínimo muere en silencio. Una heurística que funciona: si la lista de roles deja de caber en una pantalla, el modelo está absorbiendo trabajo que pertenece a otra capa.
Diseñar roles: top-down, bottom-up o ambos
La parte que ningún explicador del ranking cubre: de dónde salen los roles. El enfoque top-down los deriva de la organización y sus procesos — entrevista al negocio, nombra las funciones, asigna permisos mínimos; preciso pero lento. El bottom-up los mina de los grants existentes — agrupa quién ya tiene qué, y los roles candidatos caen solos; rápido, pero lava los errores del pasado y los convierte en política. La práctica es híbrida: mina candidatos, valídalos contra las funciones y aplica la prueba 80/20 — un puñado de roles amplios para el grueso de la organización, con las excepciones manejadas por ACLs o condiciones en lugar de roles boutique. Y una regla de implementación que sobrevive a cualquier reorganización: el código debe verificar permisos, no nombres de rol — can('posts:publish'), no hasRole('Editor') — para que redefinir un rol sea un cambio de datos, no un refactor, con el enforcement del lado del servidor, denegando por defecto.
Casos de uso comunes
- Paneles de admin y back-offices — soporte, moderación, finanzas, superadmin: las funciones mapean limpio a roles.
- Flujos de contenido y publicación — autor, editor, publicador, con separación entre escribir y lanzar.
- Permisos de equipo en SaaS B2B — owner/admin/miembro/facturación por workspace, acotados por tenant.
- Operaciones bajo compliance — separación de funciones como restricciones de rol aplicables, con la membresía de roles como artefacto de auditoría.
- El gate de roles en las capas de datos — los roles como el “quién” en los permisos a nivel de clase y las políticas por fila.
¿Deberías usar RBAC? Matriz de decisión
| Situación | Inclínate por |
|---|---|
| El acceso sigue la función de trabajo | RBAC — su juego de local |
| Los usuarios comparten registros individuales ad hoc | ACLs — los roles no pueden expresarlo |
| El contexto decide (hora, estado, tenant) | Condiciones de atributos sobre los roles |
| Un puñado de tipos de usuario, estables | RBAC con 3–7 roles amplios |
| Organigramas profundos, equipos anidados | Jerarquía de roles — o ReBAC a escala real |
| ”Solo admins y todos los demás” | Un gate de rol — no lo sobremodeles |
Limitaciones y trade-offs
- La compartición por objeto queda fuera del alcance. “Comparte este documento con Ana” no tiene respuesta en RBAC que no sea un rol por documento — esa decisión pertenece a las ACLs.
- Mismo rol, mismos poderes. Dos Editores son indistinguibles; el matiz individual exige otra capa, no un rol casi duplicado.
- La ingeniería de roles es trabajo real de arranque. Saltársela produce roles que no reflejan ni la organización ni el modelo de riesgo — y se copian para siempre.
- Los roles estáticos no ven el riesgo dinámico. La membresía de un rol no percibe horarios inusuales, dispositivos nuevos ni estados sensibles del registro; ese es territorio de atributos.
- La deriva es el estado estacionario. Sin recertificación periódica, el alcance de los roles solo crece; la auditabilidad de RBAC es una capacidad, no una garantía.
Roles en Back4app
Back4app es una plataforma open-source de Backend as a Service (BaaS) que combina base de datos gestionada, APIs REST y GraphQL generadas automáticamente, autenticación, almacenamiento de archivos y funciones serverless con Cloud Code. Aquí los roles son datos, no código: cada uno es un objeto de la clase _Role con una relation users para los miembros y una relation roles para el anidamiento — y anidar es jerarquía gratis, ya que los miembros de un rol hijo heredan lo que se les concede a sus roles padre. Los grants ocurren exactamente donde apunta la sección de composición: los nombres de rol aparecen en los permisos a nivel de clase para el trazo grueso y en las entradas de ACL por objeto para las excepciones — las pestañas de código muestran ambas mitades — con Back4app aplicando el resultado en cada solicitud REST, GraphQL y Live Query. Como los roles son objetos consultables, la gestión de membresías, las auditorías y las pantallas de admin se vuelven trabajo ordinario de base de datos: prevenir la explosión de roles como hábito de modelado, no como proyecto de gobernanza.
Preguntas frecuentes
¿Qué es RBAC en términos simples?
El acceso se concede por función de trabajo, no por persona: los permisos se asignan a roles — Editor, Admin, Soporte — y los usuarios heredan lo que llevan los roles que tienen asignados. Contratación, promoción y salida se vuelven cambios de rol en un solo lugar, en vez de ediciones de permisos dispersas por todas partes.
¿Cuál es la diferencia entre RBAC y ABAC?
RBAC decide a partir de roles predefinidos; el control de acceso basado en atributos (ABAC) evalúa atributos del usuario, del recurso y del contexto — departamento, sensibilidad, horario — en el momento de la solicitud. RBAC es más simple de razonar y auditar; ABAC es más fino y más difícil de depurar. Los sistemas maduros usan RBAC como base y agregan condiciones de atributos donde el contexto realmente importa.
¿Cuál es la diferencia entre RBAC y una ACL?
La dirección del vínculo: una ACL cuelga entradas sujeto-permiso de cada objeto; RBAC cuelga los permisos de roles que valen en todo el sistema. Se componen en lugar de competir — una entrada de ACL puede nombrar un rol, y así es como el control por objeto y la gestión de membresías en un solo lugar coexisten.
¿Cuáles son los modelos de RBAC?
El estándar define el RBAC core (usuarios, roles, permisos, sesiones), el RBAC jerárquico (los roles senior heredan los permisos de los junior) y el RBAC restringido (reglas de separación de funciones — restricciones estáticas sobre la asignación, restricciones dinámicas sobre lo que una sesión puede activar a la vez).
¿Cuáles son las tres reglas de RBAC?
De la formulación original de 1992: un sujeto solo puede actuar a través de un rol seleccionado (asignación de rol); el sujeto debe estar autorizado para ese rol (autorización de rol); y una acción solo se permite si el rol activo tiene su permiso (autorización de permiso). En conjunto: ningún acceso, salvo a través de roles.
¿Qué es la explosión de roles (role explosion)?
El crecimiento descontrolado cuando cada excepción, proyecto, región o tenant genera un rol nuevo — Gerente-Proyecto-A-Región-Oeste — hasta que los roles superan en número a los usuarios y nadie puede auditar el sistema. La causa raíz es codificar atributos contextuales como roles, en lugar de manejarlos con condiciones o entradas por objeto.
¿RBAC es lo mismo que privilegio mínimo?
No — el privilegio mínimo es el principio, RBAC es un mecanismo para perseguirlo, y solo la disciplina con los roles conecta ambos. Un rol demasiado amplio viola el privilegio mínimo desde dentro de RBAC; acotar los roles al mínimo y revisarlos periódicamente es lo que de verdad entrega el principio.
¿Qué es la separación de funciones en RBAC?
Restricciones que mantienen separados los poderes en conflicto: la separación estática impide que un usuario acumule jamás creador-de-pagos y aprobador-de-pagos; la dinámica permite tener ambos, pero nunca activarlos en la misma sesión. Es prevención de fraude expresada como regla de roles.