v1.0.0

aloux-iam

Librería Node.js para gestión de identidad y acceso (IAM) en APIs Express + MongoDB.

Autenticación

JWT, bcrypt, 2FA TOTP, rate limiting, bloqueo por intentos fallidos.

Control de acceso

Funciones → Permisos por endpoint. Cuentas de servicio con API tokens.

Multi-tenant

Estructura Empresas → Negocios → Usuarios con roles independientes.

Integraciones

AWS S3, SES, SNS · Google BigQuery · Templates de email personalizables.

Stack requerido: Node.js ≥ 16, Express ≥ 4, MongoDB ≥ 4 / Mongoose ≥ 6.

Instalación y configuración

1. Instalar

npm install aloux-iam

2. Registrar en Express

const express = require('express')
const mongoose = require('mongoose')
const cookieParser = require('cookie-parser')
const { IAMRouter } = require('aloux-iam')

const app = express()

app.use(express.json())
app.use(cookieParser())
app.use(IAMRouter)          // monta todos los endpoints /iam/*

mongoose.connect(process.env.MONGO_URI)
app.listen(3000)

3. Usar el middleware en tus propias rutas

const { IAMAuth } = require('aloux-iam')

// Protege cualquier ruta tuya con el mismo middleware
app.get('/api/mi-recurso', IAMAuth, (req, res) => {
  // req.user  → usuario autenticado con funciones/permisos
  // req.token → JWT string
  res.json({ user: req.user })
})
Importante: El middleware verifica que exista un registro en la colección permissions que coincida con el método y la ruta de cada endpoint. Si no existe, responde 403. Asegúrate de dar de alta tus endpoints en esa colección.

4. Usar los modelos de Mongoose

const { IAMUserModel, IAMFunctionsModel, IAMPermissionModel, IAMMenuModel } = require('aloux-iam')

// Consulta directa al modelo de usuario
const users = await IAMUserModel.find({ status: 'Activo' })

Variables de entorno

Configura estas variables en tu archivo .env antes de iniciar el servidor.

Autenticación y sesión

VariableRequeridaDescripciónEjemplo
AUTH_SECRETClave secreta para firmar y verificar JWTs3cr3t-muy-largo
SESSION_TIMEOpcDuración de sesión en minutos30
MAX_TOKENSOpcMáximo de sesiones activas simultáneas por usuario5
FAILED_ATTEMPSOpcIntentos de login fallidos antes de bloquear la cuenta y activar rate limit. Default: 55
SESSION_INTERRUPTOROpcSi true, valida la expiración de sesión en cada requesttrue
MASTER_PWDOpcContraseña maestra para entornos DEBUG (omite bcrypt). No usar en producción.solo-desarrollo
DEBUGOpcActiva login con MASTER_PWD y URL de Swagger en DEVtrue

Emails y notificaciones

VariableRequeridaDescripciónEjemplo
AWS_REGIONSí*Región AWS (necesaria para SES/SNS)us-east-1
AWS_EMAIL_SENDERSí*Email verificado en AWS SES usado como remitentenoreply@tuapp.com
SEND_EMAIL_USEROpcSi true, envía email de bienvenida al crear usuariotrue
SUBJECT_EMAILOpcAsunto por defecto para emails de la plataformaBienvenido
TEMPLATE_ACCOUNTOpcPath absoluto al template HTML de cuenta nueva/templates/account.html
TEMPLATE_RECOVER_PASSWORDOpcPath al template HTML para recuperar contraseña/templates/recover.html
VERIFY_ACCOUNT_URLOpcURL base para verificar cuenta de emailhttps://tuapp.com/verify
URL_VERIFY_EMAILOpcURL para confirmar cambio de emailhttps://tuapp.com/confirm-email
CHANGE_PWDOpcSi true, obliga al usuario a cambiar contraseña en primer logintrue

AWS Storage

VariableDescripciónEjemplo
AWS_BUCKETNombre del bucket S3 para archivos (fotos, favicons)mi-app-bucket

Google Cloud / BigQuery

VariableDescripciónEjemplo
PROJECT_IDID del proyecto en Google Cloudmi-proyecto-gcp
DATASET_IDID del dataset en BigQuerymi_dataset
UPLOAD_CUSTOMERSi true, sube datos de nuevos clientes a BigQuerytrue
UPLOAD_CUSTOMER_TABLENombre de la tabla destino en BigQuerymi_tabla

Historial y observabilidad

VariableDescripciónEjemplo
HISTORYSi true, registra historial de acciones en los endpoints configuradostrue
HISTORY_ENDPOINTSLista separada por comas de paths a registrar/iam/user,/iam/auth/login
SWAGGER_SERVERURL del servidor mostrado en Swagger cuando DEBUG=truehttps://api-dev.tuapp.com

Multi-app y branding

VariableDescripciónEjemplo
APPIdentificador de la aplicación. Permite cargar variables con sufijo, ej. TEMPLATE_ACCOUNT_webweb / mobile
PROJECT_NAMENombre de la app. Se inyecta en templates como +++brandName+++Mi App
BRAND_COLORColor principal de marca para templates de email#6c8ef7
BRAND_LOGOURL del logo para templates de emailhttps://cdn.tuapp.com/logo.png
FUNCTION_NAMENombre de la función asignada por defecto al crear usuario desde signupCliente

Exportaciones de la librería

ExportTipoDescripción
IAMRouterExpress RouterRouter con todos los endpoints /iam/*. Montarlo con app.use(IAMRouter).
IAMAuthMiddlewareMiddleware de autenticación JWT. Usarlo en tus propias rutas privadas.
IAMSwaggerObjectObjeto OpenAPI/Swagger listo para usar con swagger-ui-express.
IAMUserModelMongoose ModelModelo User.
IAMUserBusinessMongoose ModelModelo Business.
IAMFunctionsModelMongoose ModelModelo Functions.
IAMPermissionModelMongoose ModelModelo Permission.
IAMMenuModelMongoose ModelModelo Menu.
AlouxAWSServiceOperaciones S3 / SES / SNS.
AlouxBQServiceOperaciones Google BigQuery.
AlouxHistoryServiceControlador de historial de acciones.

Configurar control de acceso

Para proteger tus propios endpoints con aloux-iam, sigue estos pasos:

1
Dar de alta el permiso en la colección permissions

Cada endpoint tuyo necesita un documento en MongoDB con el método HTTP y el path exacto de Express.

2
Crear una Function y asignarle el permiso

Una Function actúa como rol. Crea una con POST /iam/functions y agrega el _id del permiso en su array _permissions.

3
Asignar la Function al usuario

Actualiza el usuario con PATCH /iam/user/:USER_ID agregando el _id de la función en su array _functions.

4
Proteger la ruta con IAMAuth

Usa el middleware exportado en tu app. El IAM verificará automáticamente que el usuario tenga el permiso.

Ejemplo completo

// 1. Crear el permiso
POST /iam/permission
{
  "description": "Ver productos",
  "method":      "GET",
  "api":         "productos",
  "endpoint":    "/api/productos",
  "auth":        1,
  "status":      "Activo"
}
// → { _id: "abc123", ... }

// 2. Crear la función con ese permiso
POST /iam/functions
{
  "name":         "Catálogo",
  "_permissions": ["abc123"],
  "_menus":       []
}
// → { _id: "fun456", ... }

// 3. Asignar función al usuario
PATCH /iam/user/:USER_ID
{ "_functions": ["fun456"] }

// 4. Tu endpoint protegido
const { IAMAuth } = require('aloux-iam')

app.get('/api/productos', IAMAuth, (req, res) => {
  res.json({ productos: [] })
})

Permisos default

Si un permiso tiene "default": true, cualquier usuario autenticado puede acceder al endpoint sin importar sus funciones. Útil para endpoints compartidos como perfil propio, listado de menú, etc.

POST /iam/permission
{
  "description": "Ver perfil propio",
  "method":      "GET",
  "api":         "perfil",
  "endpoint":    "/api/mi-perfil",
  "auth":        1,
  "default":     true,
  "status":      "Activo"
}

Flujo de autenticación

Cada request a un endpoint protegido pasa por el siguiente flujo:

1
Obtención del token

Se busca en el header Authorization: Bearer <token> o en la cookie token. Si no existe → 401.

2
Verificación JWT

Se verifica la firma del token con AUTH_SECRET y se extrae el _id del payload.

3
Búsqueda del usuario

Se hace User.findOne({ _id, "tokens.token": token, status: "Activo" }) con populate de funciones y permisos. Si no existe → 401.

4
Validación de expiración (opcional)

Si SESSION_INTERRUPTOR=true, verifica token.dateEnd > Date.now(). Si venció, elimina el token y devuelve 401.

5
Validación de permiso

Busca un Permission con el método HTTP y el path exacto del endpoint. Si no existe → 403. Si auth=true y no es default, verifica que el usuario tenga acceso.

6
Asignaciones al request

req.user (usuario completo), req.token (JWT string), req.permission (descripción del permiso).

Respuesta de error estándar

{
  "code":       401,
  "title":      "Error de autenticación",
  "detail":     "No se encontró el usuario",
  "suggestion": "Vuelve a iniciar sesión"
}

Endpoints de autenticación — sin token

POST/iam/auth/emailVerificar si un email existe · Rate limit activo
POST/iam/auth/loginIniciar sesión · Rate limit activo
POST/iam/auth/logoObtener logo de la empresa por email
POST/iam/auth/forgot/passwordEnviar código de recuperación de contraseña
POST/iam/auth/validate/codeValidar código de recuperación
POST/iam/auth/reset/passwordResetear contraseña con código válido
POST/iam/auth/verify/mailEnviar email de verificación de cuenta
GET/iam/auth/verify/mail/token/:tokenActivar cuenta mediante token de email
POST/iam/auth/signupRegistro de nuevo usuario
GET/iam/generatePasswordGenerar contraseña aleatoria segura

Ejemplo: Login

// Request
POST /iam/auth/login
{
  "email": "usuario@email.com",
  "pwd":   "MiContraseña123!"
}

// Response 200 — login exitoso
{
  "token":     "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "changePwd": false
}

// Response 200 — requiere 2FA
{
  "requires2FA": true,
  "needsSetup":  false,
  "tempToken":   "eyJ..."
}

Ejemplo: Verificar email

POST /iam/auth/email
{ "email": "usuario@email.com" }

// Response 200 — email existe
{ "email": true, "name": "Juan", "lastName": "Pérez" }

// Response 201 — email nuevo (se creó UserProvisional)
{ "email": false, "name": null, "_id": "..." }

Endpoints de autenticación — con token

Todos requieren header Authorization: Bearer <token>
GET/iam/auth/mePerfil del usuario autenticado
PATCH/iam/auth/profileActualizar perfil
PUT/iam/auth/profile/picturaActualizar foto de perfil (sube a S3)
PUT/iam/auth/reset/passwordCambiar contraseña estando autenticado
POST/iam/auth/send/verify/phoneEnviar código SMS para verificar teléfono
POST/iam/auth/verify/phoneValidar código de teléfono
POST/iam/auth/logoutCerrar sesión actual
PATCH/iam/auth/mailIniciar cambio de email
POST/iam/auth/validate/mailConfirmar nuevo email

2FA / TOTP

aloux-iam soporta autenticación de dos factores compatible con Google Authenticator, Authy y cualquier app TOTP.

Flujo de activación

1
Setup — generar QR

GET /iam/totp/setup — Devuelve un código QR (base64) y el secreto TOTP. El usuario lo escanea con su app.

2
Activar — confirmar escaneo

POST /iam/totp/activate con { "token": "123456" } — Valida el primer código TOTP y activa el 2FA en la cuenta.

Flujo de login con 2FA activo

1
Login normal

POST /iam/auth/login — Si el usuario tiene 2FA activo, responde { requires2FA: true, tempToken: "..." } en lugar del token real.

2
Verificar código TOTP

POST /iam/totp/verify con { "token": "123456", "tempToken": "..." } — Si el código es correcto, devuelve el JWT real.

Endpoints TOTP

GET/iam/totp/setupGenera QR y secreto TOTP
POST/iam/totp/activateActiva 2FA tras escanear QR
POST/iam/totp/verifyVerifica código TOTP en el login
PUT/iam/user/:USER_ID/totpAdmin habilita/deshabilita 2FA de un usuario

Rate limiting

Los endpoints de login están protegidos con un rate limiter in-memory sin dependencias externas.

Endpoints protegidos: POST /iam/auth/email · POST /iam/auth/login

Límite: FAILED_ATTEMPS intentos por IP (default 5)

Ventana: 15 minutos

Respuesta al superar el límite: HTTP 429

// Response 429
{
  "code":       429,
  "title":      "Demasiados intentos",
  "detail":     "Has superado el límite de intentos permitidos.",
  "suggestion": "Espera unos minutos antes de intentarlo nuevamente."
}

Además, si un usuario falla FAILED_ATTEMPS veces su contraseña, su cuenta cambia a estado Bloqueado en la base de datos. Para desbloquearlo se usa la opción de recuperación de contraseña.


Usuarios

POST/iam/userCrear usuario
GET/iam/userListar todos los usuarios
POST/iam/user/pagesListar con paginación y filtros
GET/iam/user/:USER_IDObtener usuario por ID
PATCH/iam/user/:USER_IDActualizar usuario
PUT/iam/user/:USER_ID/statusCambiar estado
PUT/iam/user/password/:USER_IDActualizar contraseña
DELETE/iam/user/:USER_IDEliminar usuario
GET/iam/user/count/allContar usuarios
GET/iam/business/userUsuarios del negocio actual
GET/iam/user/by/my/companiesUsuarios de mis empresas
PATCH/iam/add/time/:TOKENExtender duración de una sesión

Paginación (request)

POST /iam/user/pages
{
  "config": {
    "page":         1,
    "itemsPerPage": 10,
    "sort":         { "createdAt": -1 }
  },
  "filter": {
    "search": "juan"   // busca en name y lastName
  }
}

// Response
{
  "currentPage":   1,
  "totalPages":    5,
  "perPage":       10,
  "count":         48,
  "remainingPages": 4,
  "items":         [ ... ]
}

Tipos de usuario

Usuario normal

Tiene email y contraseña. Inicia sesión mediante el flujo /iam/auth/email/iam/auth/login. El token de sesión expira según SESSION_TIME. Los permisos se asignan a través de Funciones.

Cuenta de servicio

Sin email ni contraseña. Diseñada para comunicación entre servicios (machine-to-machine). Recibe un token permanente al crearse. Los permisos se asignan directamente por ID de permiso en data.apis.

Crear una cuenta de servicio

Omite email y pwd en el body. El sistema detecta automáticamente que es una cuenta de servicio y genera el token en la respuesta:

POST /iam/user
Authorization: Bearer <tu-token-admin>

{
  "name": "mi-servicio",
  "_functions": [],
  "_company": ["<COMPANY_ID>"]
}

// Response 201
{
  "_id": "64a1...",
  "name": "mi-servicio",
  "tokens": [
    {
      "token": "eyJhbGci...",   // guárdalo, no se muestra de nuevo
      "type":  "api"
    }
  ]
}

Usar el token de servicio

Incluye el token en el header Authorization de cada request, igual que un usuario normal:

Authorization: Bearer eyJhbGci...

Asignar permisos a una cuenta de servicio

En lugar de Funciones, las cuentas de servicio usan el campo data.apis: un arreglo de IDs de Permiso a los que tiene acceso. Actualiza el usuario con PATCH /iam/user/:USER_ID:

PATCH /iam/user/<SERVICE_USER_ID>
Authorization: Bearer <tu-token-admin>

{
  "data": {
    "apis": [
      "<PERMISSION_ID_1>",
      "<PERMISSION_ID_2>"
    ]
  }
}
Token permanente: El token de una cuenta de servicio no expira automáticamente. Guárdalo de forma segura (variable de entorno, gestor de secretos). Si se compromete, elimina al usuario o actualiza su lista de tokens para revocarlo.

Funciones

Las Funciones agrupan conjuntos de Permisos y Menús. Se asignan a usuarios para controlar su acceso.

POST/iam/functionsCrear función
GET/iam/functionsListar funciones
POST/iam/functions/pagesListar con paginación
GET/iam/functions/:FUNCTION_IDObtener función (incluye permisos y menús)
PATCH/iam/functions/:FUNCTION_IDActualizar función
PUT/iam/functions/:FUNCTION_ID/statusCambiar estado
DELETE/iam/functions/:FUNCTION_IDEliminar función
GET/iam/functions/count/allContar funciones

Permisos

Cada permiso representa un endpoint específico. El middleware los valida en cada request.

POST/iam/permissionCrear permiso
GET/iam/permissionListar permisos
POST/iam/permission/pagesListar con paginación y filtros
GET/iam/permission/:PERMISSION_IDObtener permiso
PATCH/iam/permission/:PERMISSION_IDActualizar permiso
PUT/iam/permission/:PERMISSION_ID/statusCambiar estado
DELETE/iam/permission/:PERMISSION_IDEliminar permiso
GET/iam/permission/count/allContar permisos

Estructura de un permiso

{
  "description": "Ver lista de usuarios",
  "method":      "GET",
  "api":         "user",
  "endpoint":    "/iam/user",
  "auth":        1,       // 1 = requiere autenticación
  "default":     false,  // true = accesible sin verificar función
  "status":      "Activo"
}
Cada endpoint de tu aplicación debe tener un registro en la colección permissions. Si el middleware no encuentra el permiso, responde 403.

Empresas (Companies)

POST/iam/companyCrear empresa
GET/iam/companyListar empresas
GET/iam/company/myMis empresas
GET/iam/company/:COMPANY_IDDetalle de empresa
PATCH/iam/company/:COMPANY_IDActualizar empresa
PATCH/iam/company/:COMPANY_ID/pictureActualizar logo
PATCH/iam/company/:COMPANY_ID/faviconActualizar favicon
GET/iam/company/:ID/identityIdentidad pública (sin auth)
PUT/iam/company/:COMPANY_ID/gkeyConfigurar Google Key
DELETE/iam/company/:COMPANY_ID/gkeyEliminar Google Key
DELETE/iam/company/:COMPANY_IDEliminar empresa

Negocios (Businesses)

Los negocios pertenecen a una empresa y pueden tener su propia Google Key para BigQuery/Storage.

POST/iam/businessCrear negocio
GET/iam/businessListar negocios
POST/iam/business/pagesListar con paginación
POST/iam/business/companyNegocios de una empresa
GET/iam/business/myMis negocios
GET/iam/business/my/company/:COMPANY_IDMis negocios de una empresa
GET/iam/business/:BUSINESS_IDDetalle del negocio
PUT/iam/business/:BUSINESS_IDActualizar negocio
PATCH/iam/business/:BUSINESS_ID/pictureActualizar logo
PATCH/iam/business/:BUSINESS_ID/faviconActualizar favicon
GET/iam/business/:ID/identityIdentidad pública (sin auth)
PATCH/iam/business/:BUSINESS_ID/useCompanyKeyUsar clave de empresa
POST/iam/business/:BUSINESS_ID/inheritKeyHeredar clave de empresa
DELETE/iam/business/:BUSINESS_IDEliminar negocio

Etiquetas (Labels)

POST/iam/labelCrear etiqueta
GET/iam/labelListar etiquetas
GET/iam/label/:LABEL_IDObtener etiqueta
PATCH/iam/label/:LABEL_IDActualizar etiqueta
PUT/iam/label/:LABEL_ID/statusCambiar estado
DELETE/iam/label/:LABEL_IDEliminar etiqueta
GET/iam/label/count/allContar etiquetas

Logs

Sistema de log para registrar eventos de negocio asociados a usuarios, empresas y negocios.

POST/iam/logCrear log (asocia automáticamente al usuario autenticado)
POST/iam/log/retrieveRecuperar logs con filtros
GET/iam/log/:LOG_IDObtener log
PATCH/iam/log/:LOG_IDActualizar log
PUT/iam/log/:LOG_ID/statusCambiar estado
DELETE/iam/log/:LOG_IDEliminar log
GET/iam/log/count/allContar logs

Historial de acciones

Registro automático de requests. Se activa por endpoint mediante variables de entorno.

Requiere HISTORY=true y lista de endpoints en HISTORY_ENDPOINTS.
POST/iam/retrieve/historyListar historial con filtros (método, descripción, usuario, fecha)
GET/iam/history/:HISTORY_IDDetalle de una entrada del historial

Cada registro contiene: método HTTP, path, payload enviado, respuesta del endpoint, usuario responsable y timestamp.


Modelo: User

Campos principales

nameStringNombre del usuario*
lastNameStringApellido
emailStringCorreo electrónico único, lowercase
pwdStringContraseña (mín. 8 chars). Se hashea automáticamente con bcrypt.
phoneStringTeléfono (máx. 13 caracteres)
urlImgStringURL de foto de perfil en S3
statusEnumActivo · Inactivo · Bloqueado
tokensArraySesiones activas. Cada token tiene token, date, dateEnd, type.
_functions[ObjectId]Funciones (roles) asignadas al usuario.
_business[ObjectId]Negocios a los que pertenece.
_company[ObjectId]Empresas a las que pertenece.
dataObjectMetadata flexible. Incluye changePwd, totp, apis.
validateKeyObjectLlaves de validación: intentos fallidos, código de reset, verificación de email/teléfono.
createdAtNumberTimestamp de creación
lastUpdateNumberTimestamp de última modificación

Modelo: Functions

nameStringNombre único de la función*
descriptionStringDescripción
_permissions[ObjectId]Permisos incluidos en esta función*
_menus[ObjectId]Elementos de menú visibles para esta función*
statusEnumActivo · Inactivo

Modelo: Permission

descriptionStringDescripción legible del permiso*
methodStringMétodo HTTP: GET, POST, PATCH, PUT, DELETE*
apiStringNombre del grupo / API*
endpointStringPath exacto del endpoint (igual al definido en Express)*
authNumber1 = requiere autenticación. Default: 1.
defaultBooleanSi true, cualquier usuario autenticado tiene acceso.
statusEnumActivo · Inactivo

Modelo: Menu

labelStringTexto visible del ítem*
descriptionStringDescripción opcional
pathStringRuta de navegación del frontend*
iconStringNombre o clase del ícono
indexNumberPosición de ordenamiento
_menuObjectIdReferencia al menú padre (submenús)
statusEnumActivo · Inactivo

Modelo: Company

nameStringNombre de la empresa (máx. 200)*
imgUrlStringURL del logo (máx. 500)
faviconUrlStringURL del favicon
dataObjectMetadata flexible
statusEnumActivo · Inactivo

Modelo: Business

nameStringNombre del negocio (máx. 200)*
imgUrlStringURL del logo
faviconUrlStringURL del favicon
_companyObjectIdEmpresa a la que pertenece
environmentEnumdev · qa · prod
gkeyObjectGoogle Key para BigQuery/Storage del negocio (credenciales de servicio GCP)
dataObjectMetadata flexible
statusEnumActivo · Inactivo

AWS — S3, SES, SNS

Disponible como AlouxAWS en las exportaciones. Requiere credenciales AWS configuradas en el entorno (AWS_REGION, AWS_BUCKET, AWS_EMAIL_SENDER).

S3 — Subir archivos al bucket

El router incluye express-fileupload de forma automática. Desde tus endpoints puedes acceder a los archivos via req.files y pasarlos directamente a AlouxAWS.upload().

const { AlouxAWS } = require('aloux-iam')

app.post('/api/upload', IAMAuth, async (req, res) => {
  const file = req.files?.archivo   // campo del form-data
  if (!file) return res.status(400).send({ error: 'No se recibió archivo' })

  // Ruta dentro del bucket (sin slash inicial)
  const path = `uploads/${Date.now()}-${file.name}`

  const url = await AlouxAWS.upload(path, file)
  // url → URL pública del archivo en S3

  res.json({ url })
})

S3 — Eliminar archivos

// Eliminar un archivo (pasa la ruta dentro del bucket)
await AlouxAWS.delete('uploads/archivo.jpg')

// Eliminar varios archivos de una sola llamada
await AlouxAWS.deleteMany([
  'uploads/foto1.jpg',
  'uploads/foto2.png'
])
Todos los archivos subidos con AlouxAWS.upload() son públicos (ACL: public-read). Úsalo solo para assets que deben ser accesibles sin autenticación (fotos de perfil, logos, etc.).

SES — Enviar email con template

El método send() lee un archivo HTML desde la ruta definida en la variable de entorno indicada, reemplaza los placeholders de marca y lo envía via AWS SES.

const { AlouxAWS } = require('aloux-iam')

// Leer template y enviar
const html = fs.readFileSync(process.env.TEMPLATE_ACCOUNT, 'utf8')
await AlouxAWS.send(
  'destinatario@email.com',  // para
  html,                        // contenido HTML
  'Bienvenido a la plataforma' // asunto
)

SES — Enviar email personalizado

Usa sendCustom() cuando quieras enviar HTML propio sin usar el sistema de templates de la librería.

const html = `
<h1>Hola, </h1>
<p>Tu pedido #12345 fue confirmado.</p>
`

await AlouxAWS.sendCustom(
  'cliente@email.com',
  html,
  'Confirmación de pedido'
)

SNS — Enviar SMS

await AlouxAWS.sendMessagePhone(
  '+521234567890',       // número en formato E.164
  'Tu código es: 4821'  // mensaje de texto
)

Templates de email — placeholders

Los archivos HTML de templates pueden usar estos tokens que se reemplazan automáticamente al enviar:

Placeholder en el HTMLSe reemplaza conVariable de entorno
+++brandName+++Nombre de la aplicaciónPROJECT_NAME
+++brandColor+++Color principal de marcaBRAND_COLOR
+++brandLogo+++URL del logoBRAND_LOGO
+++user+++Nombre del destinatario

Variables de entorno requeridas para AWS

VariableDescripciónEjemplo
AWS_REGIONRegión donde están los serviciosus-east-1
AWS_BUCKETNombre del bucket S3mi-app-bucket
AWS_EMAIL_SENDEREmail verificado en SES usado como remitentenoreply@tuapp.com
Las credenciales AWS (AWS_ACCESS_KEY_ID y AWS_SECRET_ACCESS_KEY) deben configurarse en el entorno del servidor o mediante un IAM Role si estás en EC2/ECS. La librería las toma automáticamente del SDK.

Google BigQuery

Disponible como AlouxBQ.

const { AlouxBQ } = require('aloux-iam')

// Insertar fila en una tabla
await AlouxBQ.callAppendRows({ name: 'Juan', email: 'juan@email.com' }, 'mi_tabla')

// Convertir timestamp a formato BigQuery
const dt = AlouxBQ.factoryDateTime(Date.now()) // "2026-05-25 12:00:00"
Si UPLOAD_CUSTOMER=true, al crear un usuario desde POST /iam/auth/signup se inserta automáticamente una fila en la tabla UPLOAD_CUSTOMER_TABLE.

Generador de contraseñas

GET /iam/generatePassword?length=16

// Response
{ "password": "aB3!xK9@mN2#pQ7$" }

Garantiza al menos una letra minúscula, una mayúscula, un número y un carácter especial.

Utils

const utils = require('aloux-iam/lib/config/utils')

// Escapa metacaracteres de regex en un string
utils.escapeRegex('hola (mundo)')

// Genera objeto de respuesta paginada
utils.generatePaginationResponse(count, page, itemsPerPage, items)

// Formatea y envía respuesta de error estándar
utils.responseError(res, error)

// Resuelve Google Key del negocio
utils.resolveGkey(business) // → { gkey, source }

Seguridad

Medidas aplicadas en la versión actual:

Headers HTTP

Todos los endpoints devuelven automáticamente:

HeaderValor
X-Content-Type-Optionsnosniff
X-Frame-OptionsSAMEORIGIN
X-XSS-Protection0
Strict-Transport-Securitymax-age=15552000; includeSubDomains
X-Powered-ByEliminado

Contraseñas

Hash con bcrypt. Mínimo 8 caracteres. Salting automático en pre-save.

Tokens JWT

Firmados con AUTH_SECRET. Se almacenan en DB para poder invalidarlos.

OTP criptográfico

Códigos de 4 dígitos generados con crypto.randomInt (nativo Node), sin Math.random.

Timing-safe comparison

Comparación de tokens en logout usando crypto.timingSafeEqual.

Regex seguro (ReDoS)

Búsquedas sanitizadas con String() + escapeRegex() antes de usarse en $regex, previniendo patrones maliciosos e inyección de objetos.

Bloqueo de cuenta

Tras FAILED_ATTEMPS intentos fallidos, la cuenta cambia a estado Bloqueado.