API de Roles y Permisos
Auris implementa un modelo de autorización de tres capas. Esta API cubre dos de esas capas:
-
RBAC (Control de Acceso Basado en Roles): Los roles son conjuntos de permisos con nombre. Los usuarios son asignados a roles. Los permisos usan el formato
acción:recurso(p. ej.,view:invoices,manage:users). Cada permiso puede establecerse comoALLOW,DENYoINHERIT(modelo de tres estados). -
FGA (Autorización Detallada): Un motor de tuplas de relaciones compatible con Zanzibar para el control de acceso a nivel de objeto. La capa FGA se usa cuando el RBAC a nivel de rol es insuficiente — por ejemplo, “la usuaria Alice puede ver el documento 42 específicamente, aunque no tenga
view:all_documents”.
RBAC — Gestión de Roles
Todos los endpoints de gestión de roles requieren el permiso manage:roles y el encabezado x-tenant.
/api/rolesRequires: manage:rolesLista todos los roles definidos en el tenant. Devuelve metadatos del rol pero no la lista
completa de permisos. Usa GET /api/roles/[id] o GET /api/roles/[id]/permissions para
los detalles de permisos.
Parámetros de consulta
| Parámetro | Tipo | Descripción |
|---|---|---|
page | integer | Número de página (por defecto: 1) |
limit | integer | Elementos por página (por defecto: 20) |
search | string | Filtrar por nombre de rol |
Respuesta exitosa
{
"ok": true,
"data": {
"data": [
{
"id": "role_abc123",
"name": "editor",
"description": "Can create and modify content",
"color": "#3b82f6",
"userCount": 12,
"createdAt": "2025-01-01T00:00:00Z"
}
],
"pagination": { "page": 1, "limit": 20, "total": 5, "totalPages": 1 }
}
}/api/rolesRequires: manage:rolesCrea un nuevo rol. Los nombres de rol deben ser únicos dentro del tenant y solo pueden contener caracteres alfanuméricos, guiones y guiones bajos.
Cuerpo de la solicitud
{
"name": "billing-admin",
"description": "Manages invoices and payment methods",
"color": "#f59e0b"
}description y color son opcionales.
Respuesta exitosa
{
"ok": true,
"data": {
"id": "role_def456",
"name": "billing-admin",
"description": "Manages invoices and payment methods",
"color": "#f59e0b",
"createdAt": "2025-02-18T10:00:00Z"
}
}Códigos de error
| Código | HTTP | Descripción |
|---|---|---|
NAME_TAKEN | 409 | Ya existe un rol con este nombre |
VALIDATION_ERROR | 400 | Formato de nombre de rol inválido |
/api/roles/[id]Requires: manage:rolesObtiene un rol por ID, incluyendo su lista completa de permisos con el estado ALLOW/DENY para cada permiso.
Respuesta exitosa
{
"ok": true,
"data": {
"id": "role_abc123",
"name": "editor",
"description": "Can create and modify content",
"color": "#3b82f6",
"permissions": [
{ "id": "perm_1", "key": "view:invoices", "state": "ALLOW" },
{ "id": "perm_2", "key": "create:invoices", "state": "ALLOW" },
{ "id": "perm_3", "key": "delete:invoices", "state": "DENY" }
]
}
}Estados de permiso: ALLOW (concedido explícitamente), DENY (bloqueado explícitamente), INHERIT (no establecido explícitamente — aplica el valor predeterminado del sistema, generalmente denegar).
/api/roles/[id]Requires: manage:rolesActualiza el nombre, descripción o color de un rol.
Cuerpo de la solicitud
{
"description": "Can create, modify, and publish content",
"color": "#8b5cf6"
}Respuesta exitosa
{
"ok": true,
"data": {
"id": "role_abc123",
"name": "editor",
"description": "Can create, modify, and publish content",
"color": "#8b5cf6"
}
}/api/roles/[id]Requires: manage:rolesElimina un rol. Los usuarios que tengan este rol asignado lo perderán inmediatamente. El rol es eliminado de todos los usuarios y luego eliminado del tenant.
Eliminar un rol afecta a todos los usuarios que lo tienen. Verifica el impacto usando GET /api/roles/[id], que incluye userCount, antes de eliminar.
Respuesta exitosa
{
"ok": true,
"data": { "deleted": true }
}RBAC — Gestión de Permisos
/api/roles/[id]/permissionsRequires: manage:rolesLista la configuración de permisos para un rol, agrupados por categoría. Cada permiso tiene
un state de ALLOW, DENY o INHERIT.
Respuesta exitosa
{
"ok": true,
"data": {
"permissions": [
{
"category": "Documents",
"items": [
{ "id": "perm_1", "key": "view:invoices", "label": "View Invoices", "state": "ALLOW" },
{ "id": "perm_2", "key": "create:invoices", "label": "Create Invoices", "state": "ALLOW" },
{ "id": "perm_3", "key": "delete:invoices", "label": "Delete Invoices", "state": "INHERIT" }
]
}
]
}
}/api/roles/[id]/permissionsRequires: manage:rolesActualiza los estados de permisos para un rol. Envía un array de objetos de estado de permiso. Los permisos no incluidos en el array se dejan sin cambios.
Cuerpo de la solicitud
{
"permissions": [
{ "permissionId": "perm_1", "state": "ALLOW" },
{ "permissionId": "perm_3", "state": "DENY" }
]
}Respuesta exitosa
{
"ok": true,
"data": {
"updated": 2,
"permissions": [
{ "id": "perm_1", "key": "view:invoices", "state": "ALLOW" },
{ "id": "perm_3", "key": "delete:invoices", "state": "DENY" }
]
}
}Verificación de Permisos
/api/roles/checkRequires: authenticated userVerifica si el usuario actualmente autenticado tiene un conjunto de permisos. Resuelve los permisos a través de toda la pila RBAC: anulaciones directas de usuario, asignaciones de roles y políticas predeterminadas. Opcionalmente limitado a una aplicación específica.
Este endpoint es usado por los servidores de recursos (incluido el Dashboard de Auris) para aplicar la autorización antes de realizar operaciones.
Cuerpo de la solicitud
{
"permissions": ["view:invoices", "create:invoices", "approve:expenses"],
"applicationId": "app_abc123"
}applicationId es opcional. Cuando se proporciona, solo se verifican los permisos configurados para el ámbito de esa aplicación.
Respuesta exitosa
{
"ok": true,
"data": {
"permissions": {
"view:invoices": true,
"create:invoices": true,
"approve:expenses": false
}
}
}Códigos de error
| Código | HTTP | Descripción |
|---|---|---|
VALIDATION_ERROR | 400 | permissions no es un array de strings |
FGA — Modelos de Autorización
El motor de Autorización Detallada usa un modelo basado en DSL para definir tipos de objetos, relaciones y reglas de reescritura. Antes de escribir tuplas, debes crear y activar un modelo de autorización.
Todos los endpoints de FGA requieren el encabezado x-tenant.
/api/fga/modelsRequires: manage:fga_modelsLista todos los modelos de autorización del tenant. Solo un modelo puede estar activo a la vez.
Respuesta exitosa
{
"ok": true,
"data": [
{
"id": "model_abc123",
"name": "SaaS Authorization Model",
"version": 3,
"isActive": true,
"createdAt": "2025-02-10T00:00:00Z"
}
]
}/api/fga/modelsRequires: manage:fga_modelsCrea un nuevo modelo de autorización proporcionando una definición DSL. El DSL se analiza y valida antes del almacenamiento. Si la validación falla, se devuelve un mensaje de error detallado.
Cuerpo de la solicitud
{
"name": "Document Access Model",
"dsl": "type user\n\ntype document\n relations\n define owner: [user]\n define viewer: [user] or owner\n"
}Respuesta exitosa
{
"ok": true,
"data": {
"id": "model_def456",
"name": "Document Access Model",
"version": 1,
"isActive": false,
"schema": {
"typeDefinitions": [
{ "type": "user", "relations": {} },
{ "type": "document", "relations": { "owner": { "this": {} }, "viewer": { "union": {} } } }
]
}
}
}Códigos de error
| Código | HTTP | Descripción |
|---|---|---|
DSL_PARSE_ERROR | 400 | La sintaxis del DSL es inválida — el error incluye número de línea y descripción |
DSL_VALIDATION_ERROR | 400 | El DSL es sintácticamente válido pero referencia tipos o relaciones indefinidos |
/api/fga/models/[id]Requires: view:fga_modelsObtiene un modelo de autorización específico, incluyendo su esquema completo analizado y el texto DSL.
/api/fga/models/[id]Requires: manage:fga_modelsActualiza el nombre o el DSL de un modelo. El DSL se re-analiza y valida al actualizar.
/api/fga/models/[id]/activateRequires: manage:fga_modelsEstablece este modelo como el modelo de autorización activo del tenant. Desactiva cualquier
modelo activo anteriormente. Todas las llamadas posteriores a check, expand y list-objects
usan este modelo.
Solicitud: No se requiere cuerpo.
Respuesta exitosa
{
"ok": true,
"data": { "activated": true, "modelId": "model_def456" }
}FGA — Tuplas de Relaciones
Las tuplas son los hechos del sistema de autorización. Cada tupla afirma que un sujeto tiene una relación con un objeto.
Formato de tupla: objectType:objectId#relation@subjectType:subjectId
Ejemplo: document:readme#viewer@user:alice — la usuaria alice es viewer del documento readme.
/api/fga/tuplesRequires: view:fga_tuplesLista tuplas de relaciones, con filtrado opcional.
Parámetros de consulta
| Parámetro | Tipo | Descripción |
|---|---|---|
objectType | string | Filtrar por tipo de objeto (p. ej., document) |
objectId | string | Filtrar por ID de objeto |
relation | string | Filtrar por nombre de relación |
subjectType | string | Filtrar por tipo de sujeto |
subjectId | string | Filtrar por ID de sujeto |
page | integer | Número de página |
limit | integer | Elementos por página |
Respuesta exitosa
{
"ok": true,
"data": {
"data": [
{
"id": "tuple_abc",
"objectType": "document",
"objectId": "readme",
"relation": "viewer",
"subjectType": "user",
"subjectId": "alice",
"createdAt": "2025-02-15T10:00:00Z"
}
],
"pagination": { "page": 1, "limit": 20, "total": 1, "totalPages": 1 }
}
}/api/fga/tuplesRequires: manage:fga_tuplesEscribe una única tupla de relación. La tupla se valida contra el modelo de autorización activo antes del almacenamiento.
Cuerpo de la solicitud
{
"objectType": "document",
"objectId": "readme",
"relation": "viewer",
"subjectType": "user",
"subjectId": "alice"
}Para referencias de conjuntos de sujetos (p. ej., “todos los miembros del grupo engineering pueden ver”):
{
"objectType": "document",
"objectId": "readme",
"relation": "viewer",
"subjectType": "group",
"subjectId": "engineering",
"subjectRelation": "member"
}Respuesta exitosa
{
"ok": true,
"data": {
"id": "tuple_abc",
"objectType": "document",
"objectId": "readme",
"relation": "viewer",
"subjectType": "user",
"subjectId": "alice"
}
}Códigos de error
| Código | HTTP | Descripción |
|---|---|---|
NO_ACTIVE_MODEL | 400 | No hay modelo de autorización activo contra el que validar |
INVALID_RELATION | 400 | La relación no existe en este tipo de objeto en el modelo activo |
TUPLE_EXISTS | 409 | Ya existe una tupla idéntica (se prefiere escritura idempotente — usa bulk) |
/api/fga/tuplesRequires: manage:fga_tuplesElimina una tupla de relación específica proporcionando los datos de la tupla en el cuerpo de la solicitud.
Cuerpo de la solicitud
{
"objectType": "document",
"objectId": "readme",
"relation": "viewer",
"subjectType": "user",
"subjectId": "alice"
}Respuesta exitosa
{
"ok": true,
"data": { "deleted": true }
}/api/fga/tuples/bulkRequires: manage:fga_tuplesEscribe o elimina múltiples tuplas en una única solicitud. Las operaciones se procesan atómicamente — si alguna operación falla la validación, toda la solicitud bulk es rechazada.
Cuerpo de la solicitud
{
"writes": [
{
"objectType": "document",
"objectId": "readme",
"relation": "editor",
"subjectType": "user",
"subjectId": "bob"
}
],
"deletes": [
{
"objectType": "document",
"objectId": "readme",
"relation": "viewer",
"subjectType": "user",
"subjectId": "alice"
}
]
}Respuesta exitosa
{
"ok": true,
"data": {
"written": 1,
"deleted": 1
}
}FGA — Consultas de Autorización
/api/fga/checkRequires: debug:fgaVerifica si un sujeto tiene una relación específica con un objeto. Evalúa las reglas de reescritura completas de forma recursiva. Opcionalmente devuelve el árbol de resolución para depuración.
Cuerpo de la solicitud
{
"objectType": "document",
"objectId": "readme",
"relation": "viewer",
"subjectType": "user",
"subjectId": "alice",
"explain": true
}Establece explain: true para recibir el árbol de resolución (útil para depurar por qué una verificación pasó o falló).
Respuesta exitosa
{
"ok": true,
"data": {
"allowed": true,
"resolution": {
"type": "union",
"result": true,
"children": [
{
"type": "this",
"relation": "viewer",
"result": true,
"tupleFound": "document:readme#viewer@user:alice"
}
]
}
}
}/api/fga/expandRequires: debug:fgaExpande una relación para listar todos los sujetos (usuarios o conjuntos de usuarios) que tienen una relación dada con un objeto. Devuelve una estructura de árbol que sigue las reglas de reescritura.
Cuerpo de la solicitud
{
"objectType": "document",
"objectId": "readme",
"relation": "viewer"
}Respuesta exitosa
{
"ok": true,
"data": {
"tree": {
"root": {
"type": "union",
"nodes": [
{
"type": "leaf",
"subjects": [
{ "type": "user", "id": "alice" },
{ "type": "user", "id": "bob" }
]
},
{
"type": "computed_userset",
"relation": "owner",
"subjects": [{ "type": "user", "id": "charlie" }]
}
]
}
}
}
}/api/fga/list-objectsRequires: debug:fgaLista todos los objetos de un tipo dado a los que un sujeto puede acceder mediante una relación específica. Usa búsqueda inversa a través del almacén de tuplas y las reglas de reescritura.
Cuerpo de la solicitud
{
"objectType": "document",
"relation": "viewer",
"subjectType": "user",
"subjectId": "alice"
}Respuesta exitosa
{
"ok": true,
"data": {
"objectIds": ["readme", "api-spec", "changelog"],
"total": 3
}
}Los endpoints check, expand y list-objects requieren debug:fga porque exponen la estructura interna del modelo de autorización. En producción, los servidores de recursos deben llamar a estos endpoints usando un token M2M con este permiso en lugar de exponerlos a los usuarios finales.
Relacionado
- Guía de Roles y Permisos — Cómo funciona el RBAC en Auris
- Autorización Detallada — Autorización avanzada con FGA
- Usuarios y Roles — Asigna roles desde la Consola
- API de Autorización Detallada — Verificaciones de autorización estilo Zanzibar