Marcio Cunha

¿Error de CORS en Node.js con Express? Cómo solucionarlo

Comprende por qué los navegadores bloquean solicitudes entre diferentes orígenes y aprende a configurar el paquete cors en Express.

Marcio Cunha•3 min
También disponible en:PortuguêsEnglish
Resumen
  • CORS es un mecanismo de seguridad implementado por los navegadores para evitar que sitios maliciosos accedan a datos sin autorización.
  • Cabeceras HTTP específicas como Access-Control-Allow-Origin informan al navegador qué dominios externos pueden leer una respuesta de API.
  • Las solicitudes complejas activan automáticamente una verificación preliminar llamada preflight request usando el método OPTIONS.
  • El uso del paquete cors en el ecosistema Express simplifica drásticamente la configuración de políticas de intercambio de recursos.
  • Permitir cualquier origen usando el asterisco resuelve problemas rápidamente en desarrollo pero introduce riesgos serios en producción.

¿Por qué el navegador bloquea tu API de Node.js?

Si alguna vez desarrollaste una aplicación web separando la interfaz visual del servidor, probablemente te topaste con el mensaje rojo en la consola indicando que el acceso fue denegado por políticas de seguridad. En la práctica, esto significa que la política de mismo origen (Same-Origin Policy) actuó para proteger al usuario de scripts maliciosos. Cuando el front-end corre en un puerto local e intenta buscar datos en otro puerto donde tu servidor Node.js está escuchando, el navegador bloquea la entrega.

Esta barrera protege tu navegador y datos confidenciales, no el servidor. Sin esta regla, cualquier página maliciosa podría hacer solicitudes en tu nombre a tus cuentas bancarias. Comprender esto cambia la perspectiva: un error de CORS nunca es un fallo de código en Node.js, sino una decisión del navegador.

Cómo funcionan las cabeceras de control de acceso HTTP

Para permitir que una aplicación legítima se comunique con una API, recurrimos a cabeceras HTTP específicas. La principal es Access-Control-Allow-Origin, que funciona como un pase libre indicando qué orígenes externos pueden leer el contenido. Cuando el servidor Express responde incluyendo esta cabecera, el navegador confía y entrega los datos.

Además del origen, existen otras cabeceras clave como Access-Control-Allow-Methods para verbos HTTP y Access-Control-Allow-Headers para metadatos de autenticación como el token JWT en una API REST. Configurar esto manualmente requiere manipular respuestas, haciendo casi obligatorias las bibliotecas especializadas.

Instalando y configurando el paquete cors en Express

La forma más recomendada para resolver esto en Express es usar el paquete oficial cors. Un middleware intercepta la solicitud antes de llegar a la ruta final, inyectando cabeceras de seguridad. Primero, añade la dependencia mediante tu terminal.

npm install cors

Con el paquete instalado, la configuración básica importa el módulo y lo registra en la aplicación Express antes de definir rutas:

const express = require('express');const cors = require('cors');const app = express();app.use(cors());app.get('/api/datos', (req, res) => {  res.json({ mensaje: '¡Acceso permitido con éxito!' });});app.listen(3000, () => {  console.log('Servidor corriendo en el puerto 3000');});

El peligro silencioso del asterisco en producción

Aunque permitir cualquier dominio usando el asterisco resuelve problemas rápido, esconde una trampa de seguridad en producción. Permitir que cualquier sitio consuma tus endpoints abre la puerta a abusos. Para blindar la aplicación, pasa un objeto de configuración especificando orígenes confiables mediante variables de entorno.

Personalizando reglas avanzadas para múltiples dominios

A medida que los proyectos crecen, las reglas estáticas no bastan. El paquete cors permite pasar una función personalizada para evaluar cada origen:

const origenesPermitidos = ['https://misitio.com', 'https://panel.misitio.com'];const opcionesCors = {  origin: function (origin, callback) {    if (!origin || origenesPermitidos.indexOf(origin) !== -1) {      callback(null, true);    } else {      callback(new Error('Bloqueado por política CORS'));    }  }};app.use(cors(opcionesCors));

Otro detalle crucial involucra credenciales como cookies. Los navegadores se niegan a enviar datos de sesión entre orígenes por defecto a menos que se habilite explícitamente.

Entendiendo el comportamiento de las solicitudes preliminares

Muchos fallos de CORS ocurren en operaciones como POST, PUT o DELETE con cabeceras personalizadas. El navegador ejecuta un preflight request usando el método OPTIONS para verificar seguridad antes de enviar datos. El paquete cors maneja esto automáticamente en la mayoría de los casos. Para profundizar en estos conceptos arquitectónicos en producción, consulte también nuestro análisis técnico sobre Cómo probar un transistor MOSFET en la placa con multímetro.

Consideraciones finales sobre seguridad y mejores prácticas

Resolver CORS en Node.js y Express va más allá de copiar fragmentos de código. Exige comprender el rol de seguridad del navegador. Al configurar correctamente las restricciones, garantizas una comunicación fluida sin exponer vulnerabilidades en producción.

Adoptar estas prácticas desde el inicio previene reprocesos y asegura que la arquitectura del sistema permanezca resiliente ante nuevas integraciones.