Ir al contenido

Cuentas, usuarios y acceso

Tu organización es un tenant en CORE-M — tu propia porción aislada de la plataforma. Cada petición que tú y tu equipo hacen lleva una identidad que pertenece a tu tenant, y CORE-M responde dos preguntas en cada llamada: quién eres (autenticación) y tienes permiso para hacer esto (autorización). Los datos de tu tenant se acotan automáticamente a ti y nunca son visibles para ningún otro tenant.

Esta página explica todo lo que gestionas para tu propio tenant: usuarios y el modelo de roles, permisos de página basados en grupos, el ciclo de vida del JWT, el rate limiting de inicio de sesión, las claves de API, la configuración de SSO, y cómo el aislamiento mantiene tus datos separados.

Tu tenant es tu límite de aislamiento de nivel superior. Cuando se crea tu tenant obtienes:

  • Un tenant_id único que acota cada parte de tus datos.
  • Un usuario administrador inicial (rol tenant_admin), con la contraseña almacenada con hash bcrypt.
  • Una clave de API para acceso programático, devuelta una sola vez.
  • Un grupo por defecto llamado “All Users” con todos los permisos de página (dashboard, devices, telemetry, rules, anchors). Tu administrador inicial no se añade a él — los administradores omiten las comprobaciones de grupo a través de su rol.

Los nombres de tenant son únicos; un nombre duplicado se rechaza con ALREADY_EXISTS.

Cada usuario de tu tenant tiene exactamente un rol. Los roles definen el alcance administrativo y son de grano grueso; el acceso de grano fino para los usuarios estándar proviene de los grupos.

RolAlcanceQué otorga
platform_adminTodo el sistemaReservado para el equipo de plataforma de Kronox Data que opera CORE-M. No asignable por tu tenant.
tenant_adminTu tenantAcceso completo dentro de tu tenant: usuarios, grupos, dispositivos, reglas, claves de API y configuración. Omite los permisos de grupo dentro de tu tenant.
memberTu tenantUsuario estándar. El acceso se controla por completo mediante las membresías de grupo. Sin acceso a /manage/* ni /admin/*.

Los grupos son colecciones de usuarios acotadas al tenant con un conjunto definido de permisos de página. Un usuario puede pertenecer a varios grupos, y sus permisos efectivos son la unión deduplicada de los permisos de todos sus grupos.

Permisos de página disponibles:

PermisoDa acceso a
dashboardResumen del dashboard
devicesVer y gestionar dispositivos
telemetryDashboards y gráficos de telemetry
rulesVer y gestionar reglas
anchorsDatos de prueba en blockchain en las páginas de detalle de dispositivo

Reglas de permisos en la práctica:

  • Un member sin grupos no tiene ningún acceso y ve: “Tu cuenta no tiene permisos asignados. Contacta a tu administrador.”
  • Un member que intenta una acción fuera de sus permisos se rechaza con PERMISSION_DENIED y “missing permission: rules” (o la página correspondiente).
  • Cambiar los permisos de un grupo no reescribe los tokens en vivo. Los JWT existentes quedan obsoletos y adoptan los nuevos permisos en el siguiente refresco de token.
  • Eliminar un grupo quita a todos sus miembros y recalcula sus permisos efectivos, lo que puede retirarles el acceso a algunas páginas.

Los usuarios se autentican con email y contraseña. Las contraseñas se almacenan con hash bcrypt en reposo. Las respuestas de inicio de sesión son seguras frente a ataques de temporización (timing-safe) y nunca revelan si el email o la contraseña fueron incorrectos — un usuario inexistente es indistinguible de una contraseña errónea.

Un inicio de sesión exitoso emite dos tokens, ambos firmados con Ed25519:

  • Un access token, con expiración de 15 minutos, presentado en cada llamada a la API.
  • Un refresh token, con expiración de 7 días, usado únicamente para acuñar nuevos access tokens.
flowchart TD
  login([Login: email + password]) -->|valid| issue["Issue access (15 min)<br/>+ refresh (7 day)"]
  login -->|invalid| fail["UNAUTHENTICATED<br/>(timing-safe, no field hint)"]
  issue --> use["Call API with access token"]
  use -->|access valid| ok([Request authorized])
  use -->|access expired| refresh{Refresh token<br/>still valid?}
  refresh -->|yes| rotate["Issue new access token<br/>+ rotate refresh token<br/>(old refresh invalidated)"]
  rotate --> use
  refresh -->|no| relogin([Redirect to login])

El refresh es rotatorio: cada llamada RefreshToken invalida el refresh token anterior y emite uno nuevo junto con el nuevo access token. Un refresh token expirado se rechaza con UNAUTHENTICATED, lo que obliga a un nuevo inicio de sesión.

El access token se firma con Ed25519 usando la clave de la variable de entorno AUTH_SIGNING_KEY. Los servicios downstream verifican la firma y leen los claims — no vuelven a llamar al servicio de autenticación por cada petición.

Un member del tenant T1, en los grupos “Engineering” (devices, telemetry) y “Monitoring” (dashboard, rules), recibe un access token cuyo payload se ve así:

{
"sub": "9f2c1e44-1b3a-4c8e-9d77-6a0b2f5e1c90",
"tid": "1a2b3c4d-0000-4e5f-8a9b-112233445566",
"role": "member",
"groups": [
"grp-engineering-001",
"grp-monitoring-002"
],
"permissions": [
"dashboard",
"devices",
"rules",
"telemetry"
],
"iat": 1747396800,
"exp": 1747397700
}
ClaimSignificado
subID de usuario
tidTenant ID — la clave de aislamiento para todas las consultas downstream
roleUno de platform_admin, tenant_admin, member
groupsIDs de los grupos a los que pertenece el usuario
permissionsUnión deduplicada de todos los permisos de página de los grupos
iat / expEmitido-en y expiración (ventana de 15 minutos para los access tokens)

Para mitigar el credential-stuffing y la fuerza bruta, los inicios de sesión fallidos se limitan por tasa en dos dimensiones independientes, ambas con un TTL de 900 segundos (15 minutos):

DimensiónUmbralClave de AerospikeTTL
Por email5 intentos fallidos en 15 min → bloquea el 6.ºloginrl:{email_hash}900s
Por IP de origen20 intentos fallidos en 15 min → bloquea el 21.ºloginrl:ip:{ip}900s

Una petición limitada por tasa se rechaza con RESOURCE_EXHAUSTED y “too many login attempts, try again later”. La respuesta no revela si la cuenta existe, y corem_auth_login_rate_limited_total se incrementa. Como el estado de bloqueo vive en una clave de Aerospike con un TTL, el límite se libera por sí solo una vez que la ventana expira — no hay ningún paso de desbloqueo manual.

Las claves de API autentican las llamadas de dispositivo a plataforma y las llamadas programáticas hacia tu tenant.

  • Formato: prefijo sk_live_ seguido de 32 bytes criptográficamente aleatorios, codificados en formato URL-safe.
  • Almacenamiento: solo se almacena el hash — nunca la clave en bruto.
  • Visualización: la clave en bruto se devuelve exactamente una vez en la creación. No hay forma de recuperarla más tarde; si la pierdes, la rotas.

Presentar una clave como Authorization: Bearer sk_live_… permite a CORE-M resolver tu tenant_id (y, para las claves de dispositivo, el device_id) y acotar la petición a tu tenant. Una clave revocada se rechaza con UNAUTHENTICATED.

Configuración de SSO (solo configuración en v1)

Sección titulada «Configuración de SSO (solo configuración en v1)»

CORE-M almacena y valida la configuración del proveedor de SSO para tu tenant para SAML 2.0 y OIDC.

CampoSAML 2.0OIDC
Protocolosamloidc
Metadatos / discovery del IdPURL del XML de metadatos o XML subidoDiscovery URL (.well-known/openid-configuration)
Entity ID / Client IDSP Entity IDClient ID
Client SecretN/DClient Secret (cifrado en reposo)
HabilitadoSi la configuración almacenada está habilitada para una integración futuraIgual

Una prueba de configuración comprueba que el endpoint de metadatos del IdP o de discovery de OIDC es alcanzable y válido, e informa los atributos descubiertos. La prueba nunca crea ni actualiza usuarios de CORE-M.

El aislamiento se aplica en cada petición, no como característica de una pantalla concreta:

  1. Llega una petición con un JWT o una clave de API.

  2. CORE-M extrae tu tenant_id (del claim tid o de la clave de API) y lo adjunta a la petición.

  3. Cada lectura y escritura se acota a ese tenant_id, de modo que una petición hecha bajo tu tenant nunca puede direccionar los datos de otro tenant.

  4. Cualquier acceso entre tenants se rechaza con PERMISSION_DENIED y se registra para auditoría.

Por eso el claim tid importa tanto: es el único valor que fija una petición entera a la porción de la plataforma de tu tenant.