Este documento describe las medidas de seguridad implementadas en la aplicación.
- Access Tokens: 15 minutos de duración (corto para minimizar riesgo)
- Refresh Tokens: 90 días de duración (sesión "infinita" pero renovable)
- Almacenamiento: Tokens en localStorage (consideración: migrar a httpOnly cookies en futuro)
- Revocación: Sistema de refresh tokens permite revocar sesiones específicas
- Secrets: JWT_SECRET y REFRESH_SECRET son OBLIGATORIOS (aplicación no inicia sin ellos)
- Hashing: PBKDF2 con SHA-512
- Iteraciones: 100,000 (resistente a ataques de fuerza bruta)
- Salt: 32 bytes aleatorios por usuario
- Comparación:
crypto.timingSafeEqual()para prevenir timing attacks
- Cada dispositivo obtiene un refresh token único
- Tokens pueden revocarse individualmente
- Tabla
RefreshTokenen base de datos con campos:tokenId: Identificador únicouserId: Usuario propietarioexpiresAt: Fecha de expiraciónrevokedAt: Permite invalidar tokens
<!-- Security Headers -->
X-Content-Type-Options: nosniff X-Frame-Options: DENY X-XSS-Protection: 1;
mode=block Referrer-Policy: strict-origin-when-cross-origin Permissions-Policy:
geolocation=(), microphone=(), camera=()Content-Security-Policy: Protección completa contra XSS
- defaultSrc: ["'self'"]
- styleSrc: ["'self'", "'unsafe-inline'"] // React inline styles
- scriptSrc: ["'self'", "'unsafe-eval'"] // Vite dev mode
- imgSrc: ["'self'", "data:", "https:", "blob:"]
- connectSrc: TikTok APIs + frontend
- fontSrc: ["'self'", "data:", "https:"]
- objectSrc: ["'none'"]
- mediaSrc: ["'self'", "blob:", "data:", "https:"]
- frameSrc: ["'none'"]
- baseUri: ["'self'"]
- formAction: ["'self'"]
- upgradeInsecureRequests: true (production)
Strict-Transport-Security: HTTPS obligatorio (31536000s)
- maxAge: 31536000 (1 año)
- includeSubDomains: true
- preload: true
X-Frame-Options: DENY (previene clickjacking)
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Referrer-Policy: strict-origin-when-cross-origin
Permitted-Cross-Domain-Policies: none- General API: 100 requests / 15 minutos
- Auth (login): 5 intentos / 15 minutos (skipSuccessfulRequests)
- Registro: 3 registros / 1 hora por IP
- Emails: 3 envíos / 1 hora (verificación, reset)
- Uploads: 20 uploads / 1 hora
- API Endpoints: 50 requests / 15 minutos
RateLimit-Limit: Límite máximoRateLimit-Remaining: Requests restantesRateLimit-Reset: Timestamp de reset
- Mensajes en español para mejor UX
- Status 429 (Too Many Requests)
- Headers estándar incluidos
- Origins permitidos configurables vía
ALLOWED_ORIGINS - Whitelist de dominios específicos
- Soporte para Vercel preview deployments (
*.vercel.app) - Credentials habilitados para cookies
- Todas las peticiones CORS son logueadas
- Origins bloqueados se registran con detalles
- Códigos de 64 caracteres (alta entropía)
- Válidos por 24 horas
- Un solo uso (se marcan como usados)
- Solo verificación vía URL (sin formulario manual)
- Códigos de 64 caracteres
- Válidos por 1 hora (ventana corta)
- Un solo uso
- Solo reset vía URL del email
JWT_SECRET=<secret-key> # OBLIGATORIO
REFRESH_SECRET=<refresh-secret> # OBLIGATORIO
ENCRYPTION_KEY=<encryption-key> # OBLIGATORIO
DATABASE_URL=<database-url> # OBLIGATORIO
RESEND_API_KEY=<resend-key> # Para emails
ALLOWED_ORIGINS=<origins> # Para CORSVITE_API_URL=<api-url> # URL del backend- ✅ JWT_SECRET presente (falla si no está)
- ✅ REFRESH_SECRET presente (falla si no está)
- ✅ ENCRYPTION_KEY presente y funcional
- ✅ Conexión a base de datos
- ✅ Validación de tokens en cada request
- ✅ Verificación de usuario existe en DB
- ✅ Comprobación de tokens no revocados
- ✅ Validación de expiración de tokens
- Frontend verifica expiración cada 5 minutos
- Refresh automático si quedan < 5 minutos
- Retry automático en 401 con nuevo token
- Prevención de refreshes concurrentes
1. Token expira en 5 minutos
2. Sistema detecta y refresca automáticamente
3. Usuario no ve interrupción
4. Si refresh falla → logout automático
- Hashing robusto de contraseñas (PBKDF2)
- Tokens JWT con expiración corta
- Refresh tokens para sesiones largas
- Headers de seguridad (Helmet)
- Content Security Policy completo
- CORS restrictivo
- Rate limiting por ruta
- Validación de entradas
- Logging de seguridad
- HTTPS enforcement (HSTS)
- Protección contra timing attacks
- Codes de un solo uso para emails
- SEO optimizado (meta tags, Open Graph, Twitter Cards)
- Structured data (JSON-LD)
- PWA manifest para instalación
- Robots.txt y Sitemap.xml
- DNS prefetch para performance
- Permissions Policy
- Rate limiting basado en usuario (además de IP)
- 2FA (autenticación de dos factores)
- Migrar tokens a httpOnly cookies
- Audit logs completos
- Detección de dispositivos nuevos
- Notificaciones de login desde dispositivos nuevos
- Captcha en login/register
- IP whitelisting para admin
- WAF (Web Application Firewall)
- Penetration testing regular
Si encuentras una vulnerabilidad de seguridad, por favor:
- NO abras un issue público
- Envía un email a: security@subiteya.com.ar
- Incluye:
- Descripción de la vulnerabilidad
- Pasos para reproducirla
- Impacto potencial
- Sugerencias de mitigación (opcional)
Responderemos en 48 horas y trabajaremos en un fix prioritario.
Última actualización: Noviembre 10, 2025 Versión de documento: 2.0
- Title: Optimizado con keywords principales
- Description: 155 caracteres, descriptivo y atractivo
- Keywords: Palabras clave relevantes
- Canonical: URL canónica definida
- Author: Atribución de autor
- Robots: Directivas para crawlers
- og:type, og:url, og:title, og:description
- og:image con dimensiones (1200x630)
- og:site_name y og:locale
- twitter:card (summary_large_image)
- twitter:title, twitter:description, twitter:image
- twitter:creator
- Schema.org WebApplication
- Información de la app (nombre, descripción, URL)
- Categoría y sistema operativo
- Precio y moneda
- Rating agregado
- Lista de features
- Manifest.json completo
- Icons (192x192, 512x512)
- Theme color y background color
- Display standalone
- Shortcuts para acciones rápidas
- Share target para compartir videos
- DNS prefetch para API
- Preconnect para recursos externos
- Lazy loading de imágenes (implementado en React)
- Sitemap.xml para indexación
- Robots.txt para crawlers