Skip to Content

API de Roles y Permisos

Auris implementa un modelo de autorización de tres capas. Esta API cubre dos de esas capas:

  1. 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 como ALLOW, DENY o INHERIT (modelo de tres estados).

  2. 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.

GET/api/rolesRequires: manage:roles

Lista 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ámetroTipoDescripción
pageintegerNúmero de página (por defecto: 1)
limitintegerElementos por página (por defecto: 20)
searchstringFiltrar 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 } } }

POST/api/rolesRequires: manage:roles

Crea 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ódigoHTTPDescripción
NAME_TAKEN409Ya existe un rol con este nombre
VALIDATION_ERROR400Formato de nombre de rol inválido

GET/api/roles/[id]Requires: manage:roles

Obtiene 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).


PUT/api/roles/[id]Requires: manage:roles

Actualiza 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" } }

DELETE/api/roles/[id]Requires: manage:roles

Elimina 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

GET/api/roles/[id]/permissionsRequires: manage:roles

Lista 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" } ] } ] } }

PUT/api/roles/[id]/permissionsRequires: manage:roles

Actualiza 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

POST/api/roles/checkRequires: authenticated user

Verifica 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ódigoHTTPDescripción
VALIDATION_ERROR400permissions 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.

GET/api/fga/modelsRequires: manage:fga_models

Lista 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" } ] }

POST/api/fga/modelsRequires: manage:fga_models

Crea 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ódigoHTTPDescripción
DSL_PARSE_ERROR400La sintaxis del DSL es inválida — el error incluye número de línea y descripción
DSL_VALIDATION_ERROR400El DSL es sintácticamente válido pero referencia tipos o relaciones indefinidos

GET/api/fga/models/[id]Requires: view:fga_models

Obtiene un modelo de autorización específico, incluyendo su esquema completo analizado y el texto DSL.


PUT/api/fga/models/[id]Requires: manage:fga_models

Actualiza el nombre o el DSL de un modelo. El DSL se re-analiza y valida al actualizar.


POST/api/fga/models/[id]/activateRequires: manage:fga_models

Establece 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.

GET/api/fga/tuplesRequires: view:fga_tuples

Lista tuplas de relaciones, con filtrado opcional.

Parámetros de consulta

ParámetroTipoDescripción
objectTypestringFiltrar por tipo de objeto (p. ej., document)
objectIdstringFiltrar por ID de objeto
relationstringFiltrar por nombre de relación
subjectTypestringFiltrar por tipo de sujeto
subjectIdstringFiltrar por ID de sujeto
pageintegerNúmero de página
limitintegerElementos 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 } } }

POST/api/fga/tuplesRequires: manage:fga_tuples

Escribe 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ódigoHTTPDescripción
NO_ACTIVE_MODEL400No hay modelo de autorización activo contra el que validar
INVALID_RELATION400La relación no existe en este tipo de objeto en el modelo activo
TUPLE_EXISTS409Ya existe una tupla idéntica (se prefiere escritura idempotente — usa bulk)

DELETE/api/fga/tuplesRequires: manage:fga_tuples

Elimina 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 } }

POST/api/fga/tuples/bulkRequires: manage:fga_tuples

Escribe 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

POST/api/fga/checkRequires: debug:fga

Verifica 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" } ] } } }

POST/api/fga/expandRequires: debug:fga

Expande 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" }] } ] } } } }

POST/api/fga/list-objectsRequires: debug:fga

Lista 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