Inicio > Cursos > Node.js y Express > Seguridad en APIs
Node.js y ExpressTesting y ProducciónLección 18 de 20

Seguridad en APIs

La seguridad en APIs REST tiene múltiples capas. helmet agrega headers HTTP de seguridad. express-rate-limit protege contra ataques de fuerza bruta. CORS configurado correctamente previene requests no autorizados. La sanitización previene inyección. Nunca expongas stack traces en producción.

// npm install helmet express-rate-limit
const express = require('express');
const helmet = require('helmet');
const rateLimit = require('express-rate-limit');
const cors = require('cors');

const app = express();

// 1. HELMET — agrega headers de seguridad HTTP automáticamente
// X-Content-Type-Options, X-Frame-Options, Strict-Transport-Security, etc.
app.use(helmet());

// 2. CORS — configurado correctamente (no usar origin: "*" en producción)
const corsOptions = {
  origin: (origin, callback) => {
    const permitidos = [
      'https://miapp.com',
      'https://www.miapp.com',
      'http://localhost:3000', // solo desarrollo
    ];
    if (!origin || permitidos.includes(origin)) {
      callback(null, true);
    } else {
      callback(new Error(`CORS: origen ${origin} no permitido`));
    }
  },
  methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  credentials: true,
};
app.use(cors(corsOptions));

// 3. RATE LIMITING — limitar peticiones por IP
const limiterGeneral = rateLimit({
  windowMs: 15 * 60 * 1000, // ventana de 15 minutos
  max: 100,                  // máximo 100 requests por IP por ventana
  standardHeaders: true,
  legacyHeaders: false,
  message: { error: 'Demasiadas peticiones. Intenta en 15 minutos.' },
});

// Rate limit más estricto para auth
const limiterAuth = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 10, // solo 10 intentos de login por 15min
  message: { error: 'Demasiados intentos. Cuenta bloqueada 15 minutos.' },
});

app.use(limiterGeneral);
app.use('/api/v1/auth/login', limiterAuth);

// 4. SANITIZACIÓN — nunca confiar en el input
app.use(express.json({ limit: '10kb' })); // limitar tamaño del body

// 5. MANEJO DE ERRORES — no exponer detalles en producción
app.use((err, req, res, next) => {
  const isProd = process.env.NODE_ENV === 'production';
  res.status(err.status || 500).json({
    error: isProd ? 'Error interno' : err.message,
    // stack NUNCA en producción:
    ...(isProd ? {} : { stack: err.stack })
  });
});
ConsejoLos 5 headers más importantes que agrega helmet: Content-Security-Policy (previene XSS), X-Frame-Options (previene clickjacking), Strict-Transport-Security (fuerza HTTPS), X-Content-Type-Options (previene MIME sniffing), Referrer-Policy.
← Variables de Entorno y ConfigDeploy con PM2 y Nginx →

Practica esta lección

Resuelve los ejercicios del curso de Node.js y Express en la app, gratis y con corrección automática.

Empezar a practicar