Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/JuanM84/gestor-visitas/llms.txt

Use this file to discover all available pages before exploring further.

El sistema de autenticación de la API se basa en JSON Web Tokens (JWT). El flujo es simple: el cliente envía sus credenciales al único endpoint público de la API — POST /api/auth/login —, recibe un token firmado y lo adjunta a todas las peticiones posteriores en la cabecera Authorization. No existe registro de sesiones en el servidor; la validez se determina enteramente a partir del token.

POST /api/auth/login

Este es el único endpoint que no requiere autenticación. Recibe las credenciales del usuario, las verifica contra la base de datos y, si son correctas, devuelve un token JWT junto con los datos básicos del usuario.
Si el usuario está marcado como inactivo en el sistema, el login será rechazado con 401 aunque las credenciales sean correctas. Contacta al administrador para reactivar la cuenta.

Petición

POST /api/auth/login
POST /api/auth/login HTTP/1.1
Content-Type: application/json

Cuerpo de la petición

email
string
required
Dirección de correo electrónico del usuario registrado en el sistema. Se normaliza (trim) antes de la búsqueda.
password
string
required
Contraseña en texto plano. El servidor la compara contra el hash bcrypt almacenado en la base de datos.
{
  "email": "admin@tunel.com",
  "password": "mi_contraseña_segura"
}

Respuestas

El servidor devuelve el token JWT y los datos del usuario autenticado.
token
string
required
Token JWT firmado. Debe incluirse en todas las peticiones posteriores como Authorization: Bearer <token>.
usuario
object
required
Datos del usuario autenticado.
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "usuario": {
    "id": 1,
    "nombre": "Juan García",
    "email": "admin@tunel.com",
    "rol": "Admin"
  }
}

Ejemplo con curl

curl -X POST http://localhost:3000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email": "admin@tunel.com", "password": "mi_contraseña_segura"}'

Cómo usar el token en peticiones posteriores

Una vez obtenido el token, inclúyelo en la cabecera Authorization de todas las peticiones a endpoints protegidos, usando el esquema Bearer.
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Ejemplo completo: login y petición autenticada

# 1. Iniciar sesión y capturar el token
TOKEN=$(curl -s -X POST http://localhost:3000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email": "admin@tunel.com", "password": "mi_contraseña_segura"}' \
  | jq -r '.token')

echo "Token obtenido: $TOKEN"

# 2. Usar el token en una petición protegida
curl -X GET http://localhost:3000/api/visitas \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json"

Ejemplo en JavaScript (fetch)

// 1. Login
const loginResponse = await fetch('http://localhost:3000/api/auth/login', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ email: 'admin@tunel.com', password: 'mi_contraseña_segura' })
});

const { token, usuario } = await loginResponse.json();

// 2. Guardar el token (p. ej. en localStorage o memoria)
localStorage.setItem('auth_token', token);

// 3. Petición autenticada posterior
const visitasResponse = await fetch('http://localhost:3000/api/visitas', {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${localStorage.getItem('auth_token')}`
  }
});

const visitas = await visitasResponse.json();
En aplicaciones de producción, considera almacenar el token en memoria o en una cookie HttpOnly en lugar de localStorage para reducir la exposición a ataques XSS.

Contenido del token JWT

El token es un JWT firmado con el algoritmo HS256. Su payload incluye los siguientes campos:
CampoTipoDescripción
idnumberIdentificador único del usuario
nombrestringNombre completo del usuario
rolstringRol del usuario (Admin o Guía)
iatnumberTimestamp de emisión (Unix epoch)
expnumberTimestamp de expiración (Unix epoch)
Puedes decodificar el payload en el cliente sin necesidad de la clave secreta para leer estos campos. La verificación de firma ocurre exclusivamente en el servidor.
// Decodificar el payload (sin verificar firma)
const payload = JSON.parse(atob(token.split('.')[1]));
console.log(payload.rol);    // "Admin" | "Guía"
console.log(payload.nombre); // "Juan García"

Expiración del token

La duración del token se controla con la variable de entorno JWT_EXPIRY. Si no está definida, el valor por defecto es 24h.
El formato de JWT_EXPIRY sigue la notación de la librería jsonwebtoken: 60 (segundos), 2d (días), 10h (horas), 7d (días), etc.
Cuando un token expira, cualquier petición con ese token devolverá:
{
  "error": "Token inválido o expirado. Por favor, inicie sesión nuevamente."
}
El cliente debe redirigir al usuario al login cuando reciba este error 401.

Errores de autenticación

La petición no incluye la cabecera Authorization o no tiene el esquema Bearer.
{
  "error": "Acceso denegado. Se requiere un token de autenticación."
}
Solución: Incluir Authorization: Bearer <token> en todas las peticiones protegidas.
El token está malformado, fue firmado con una clave diferente, o su tiempo de vida ha expirado.
{
  "error": "Token inválido o expirado. Por favor, inicie sesión nuevamente."
}
Solución: Realizar un nuevo login para obtener un token fresco.
El servidor no tiene definida la variable de entorno JWT_SECRET. Este es un error de configuración del entorno.
{
  "error": "Error de configuración del servidor."
}
Solución: Definir JWT_SECRET en las variables de entorno del servidor y reiniciarlo.

Control de acceso por rol

Algunos endpoints están restringidos al rol Admin. El middleware verificarRol se aplica sobre esas rutas y comprueba el campo rol dentro del payload del token.

Flujo del middleware verificarRol

1

Verificar token

El middleware verificarToken valida la firma del JWT y adjunta el payload decodificado al objeto de petición como req.usuario.
2

Verificar rol

El middleware verificarRol(['Admin']) comprueba que req.usuario.rol esté incluido en la lista de roles permitidos.
3

Acceso concedido o denegado

Si el rol coincide, la petición continúa al controlador. Si no coincide, el servidor devuelve 403 Forbidden inmediatamente.

Respuesta 403 por rol insuficiente

{
  "error": "Acceso denegado. No tienes permisos suficientes para realizar esta acción."
}

Ejemplo: acceso a un endpoint exclusivo de Admin

# Con un usuario de rol "Guía" intentando acceder a un recurso de Admin
curl -X GET http://localhost:3000/api/usuarios \
  -H "Authorization: Bearer <token_de_guia>"

# Respuesta:
# HTTP/1.1 403 Forbidden
# {
#   "error": "Acceso denegado. No tienes permisos suficientes para realizar esta acción."
# }
El rol Guía no puede gestionar usuarios, ver estadísticas de administración ni modificar la configuración del sistema. Estos endpoints requieren explícitamente el rol Admin.

Build docs developers (and LLMs) love