Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Auth API (Rust + Axum + MySQL + TOTP)

Backend de autenticacion seguro con TOTP, JWT y auditoria de seguridad en base de datos.

Estado del proyecto

  • Listo como base para evolucionar a un sistema de autenticacion de escala mayor.
  • Incluye hardening inicial de sesiones, rate limiting y logging de seguridad.

Descripcion

API de autenticacion con segundo factor TOTP, JWT y persistencia en MySQL.

Funciones principales:

  • Registro en dos pasos con TOTP.
  • Login con password + codigo TOTP.
  • Endpoint de perfil autenticado.
  • Hash de password con Argon2id (libsodium).
  • Cifrado de secreto TOTP con XChaCha20-Poly1305 (libsodium).
  • Rate limiting DB-backed para login y enroll start.
  • Auditoria de requests y eventos de seguridad en base de datos (IP, user-agent, ruta, resultado).

Demo visual del frontend

Espacio para capturas principales:

  1. Pantalla de login: Pantalla de login

  2. Flujo de registro y QR: Flujo de registro y QR Flujo de registro y QR Flujo de registro y sesión iniciada

Stack

  • Rust (edition 2024)
  • Axum + Tokio
  • SQLx (MySQL)
  • libsodium-rs
  • jsonwebtoken
  • google-authenticator
  • fast_qr

Endpoints

Base URL: http://localhost:3333

  • GET /api/health/app
  • GET /api/health/crypto
  • POST /api/auth/enroll/start
  • POST /api/auth/enroll/refresh
  • POST /api/auth/enroll/verify
  • POST /api/auth/login
  • GET /api/auth/me
  • POST /api/auth/logout

Quickstart

  1. Configura variables de entorno en .env.
  2. Levanta MySQL y confirma DATABASE_URL.
  3. Ejecuta migraciones automaticas al iniciar con RUN_DB_INIT=true.
  4. Inicia backend con cargo run.
  5. Inicia frontend en frontend_example con npm run dev.

Flujo de enrolamiento

  1. POST /api/auth/enroll/start con name, email, password.
  2. El backend responde setup_token, qr_base64 y expires_at.
  3. Si el QR expira, el cliente puede pedir uno nuevo con /api/auth/enroll/refresh usando setup_token.
  4. El cliente escanea QR y envia current_code a /api/auth/enroll/verify.
  5. Si valida, se crea usuario final y se emite JWT.

Aclaracion importante:

  • El QR no "expira por limitacion tecnica" del formato.
  • La expiracion es una medida de seguridad intencional para reducir la ventana de abuso (por ejemplo, clonacion/reuso de un QR filtrado o capturado por terceros).

Seguridad

  • Password hashing: Argon2id via libsodium crypto_pwhash.
  • Secreto TOTP cifrado en reposo (XChaCha20-Poly1305).
  • JWT con validacion de issuer y audience.
  • Sesion en cookie HttpOnly + SameSite=Strict (ademas de token en payload para compatibilidad).
  • Mensajes de error uniformes en rutas sensibles.
  • Bloqueo por intentos fallidos en login y enroll start.
  • Logging de seguridad para alta de usuarios, intentos de login, bloqueos y logout.

Auditoria y monitoreo

  • Tabla request_logs: guarda metodo, path, status_code, IP, user-agent y duracion por request.
  • Tabla security_events: guarda eventos semanticos de seguridad (login, user_created, enroll_verify, etc.) con outcome y contexto.
  • Limpieza automatica:
    • request_logs: retencion de 90 dias.
    • security_events: retencion de 180 dias.

Migraciones

  • La migracion del sistema de logs/auditoria es: migrations/202604040002_audit_logging.sql.
  • Se aplica automaticamente al iniciar el backend si RUN_DB_INIT=true|1.

Consultas utiles de auditoria

Ultimos eventos de seguridad:

SELECT created_at, event_type, outcome, ip_address, email, route, details
FROM security_events
ORDER BY created_at DESC
LIMIT 100;

IPs con mas fallos de login en 24h:

SELECT ip_address, COUNT(*) AS failed_attempts
FROM security_events
WHERE event_type = 'login'
  AND outcome IN ('invalid_password', 'invalid_totp', 'rate_limited', 'invalid_input')
  AND created_at >= DATE_SUB(UTC_TIMESTAMP(), INTERVAL 1 DAY)
GROUP BY ip_address
ORDER BY failed_attempts DESC
LIMIT 20;

Endpoints con mas errores HTTP recientes:

SELECT path, status_code, COUNT(*) AS hits
FROM request_logs
WHERE created_at >= DATE_SUB(UTC_TIMESTAMP(), INTERVAL 1 DAY)
  AND status_code >= 400
GROUP BY path, status_code
ORDER BY hits DESC
LIMIT 30;

Variables de entorno

Requeridas:

  • DATABASE_URL
  • JWT_SECRET
  • TOTP_ENC_KEY (base64 de 32 bytes)
  • FRONTEND_ORIGIN

Opcionales:

  • RUN_DB_INIT=true|1
  • QR_MODULE_COLOR (default #000000)
  • QR_BACKGROUND_COLOR (default #FFFFFF)
  • ENROLL_QR_EXPIRES_SECONDS (default 600, 10 minutos)
  • ENROLL_SESSION_MAX_LIFETIME_SECONDS (default 1800, limite absoluto de vida de un setup_token)
  • JWT_EXPIRES_SECONDS (default 3600, min 300, max 86400)
  • EXPOSE_CRYPTO_HEALTH (default false; oculta /api/health/crypto en produccion)
  • AUTH_COOKIE_SECURE (default auto por FRONTEND_ORIGIN https)
  • PASSWORD_HASH_PROFILE (interactive|moderate|sensitive, default moderate)

Ejemplo .env:

DATABASE_URL=mysql://user:password@127.0.0.1:3306/auth_api
JWT_SECRET=super_secret_jwt_key_very_long_random_value
TOTP_ENC_KEY=BASE64_DE_32_BYTES
FRONTEND_ORIGIN=http://localhost:5173
RUN_DB_INIT=true
QR_MODULE_COLOR="#F15025"
QR_BACKGROUND_COLOR="#00000000"
ENROLL_QR_EXPIRES_SECONDS=600
ENROLL_SESSION_MAX_LIFETIME_SECONDS=1800
JWT_EXPIRES_SECONDS=3600
EXPOSE_CRYPTO_HEALTH=false
AUTH_COOKIE_SECURE=false
PASSWORD_HASH_PROFILE=moderate

Contratos JSON (resumen)

POST /api/auth/enroll/start request:

{
  "name": "Juan Perez",
  "email": "juan@example.com",
  "password": "MiPassword#2026"
}

POST /api/auth/enroll/start response:

{
  "status": "success",
  "data": {
    "setup_token": "uuid",
    "qr_base64": "...",
    "expires_at": "2026-04-04T20:00:00Z"
  }
}

POST /api/auth/enroll/verify request:

{
  "setup_token": "uuid",
  "current_code": "123456"
}

POST /api/auth/login request:

{
  "email": "juan@example.com",
  "password": "MiPassword#2026",
  "current_code": "123456"
}

GET /api/auth/me header:

  • Authorization: Bearer (opcional)

Nota de sesion:

  • /api/auth/login y /api/auth/enroll/verify emiten cookie HttpOnly llamada auth_token.
  • /api/auth/me acepta cookie o bearer.
  • /api/auth/logout limpia la cookie.

Ejecutar

cargo check
cargo run

Servidor: http://localhost:3333

Licencia

Este proyecto esta bajo licencia MIT. Revisa el archivo LICENSE.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages