B. Petición con Preflight (OPTIONS)
En peticiones complejas (ej. métodos PUT/DELETE o envío de JSON), el navegador realiza primero una petición de verificación OPTIONS. Si el servidor la rechaza, la petición real nunca llega a enviarse.
Cabeceras CORS esenciales
Para configurar correctamente la comunicación de origen cruzado en servidores, se utilizan las siguientes cabeceras de respuesta HTTP:
-
Access-Control-Allow-Origin: Especifica qué orígenes pueden acceder al recurso. Puede ser un origen explícito (ej.https://mi-app.com) o un wildcard (*). -
Access-Control-Allow-Methods: Lista los métodos HTTP permitidos en peticiones cruzadas (ej.GET, POST, PUT, DELETE, OPTIONS). -
Access-Control-Allow-Headers: Lista las cabeceras personalizadas que el cliente puede enviar en la petición real. -
Access-Control-Allow-Credentials: Indica si la respuesta a la petición se puede exponer cuando la petición se realiza con credenciales (como cookies o cabeceras de autorización HTTP). Si se establece entrue,Access-Control-Allow-Originno puede ser*y debe ser un origen específico.
Cómo se usa: Implementación en Node.js
Para corregir los errores de CORS, la configuración debe realizarse en el lado del servidor. La forma estándar y recomendada de habilitarlo en un backend Node.js con Express es utilizando el paquete oficial cors:
npm install cors
1. Configuración Estática Básica
Si tienes un conjunto estático de dominios permitidos:
const express = require('express');
const cors = require('cors');
const app = express();
// Opciones de configuración estática de CORS
const corsOptions = {
origin: ['https://mi-frontend.com', 'https://mi-admin-dashboard.com'],
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true,
optionsSuccessStatus: 200 // Habilita soporte para navegadores antiguos
};
// Registrar el middleware globalmente
app.use(cors(corsOptions));
app.get('/api/data', (req, res) => {
res.json({ message: "CORS configurado con éxito" });
});
app.listen(3000);
2. Configuración Dinámica con Whitelist (Evitar conflictos con Credentials)
Como vimos en los gotchas de seguridad, si necesitas habilitar credentials: true, no puedes usar el wildcard (*). Si tu lista de orígenes debe verificarse dinámicamente, puedes configurar origin como una función:
const express = require('express');
const cors = require('cors');
const app = express();
// Lista de dominios permitidos (Whitelist)
const whitelist = ['https://mi-frontend.com', 'https://mi-admin-dashboard.com'];
const corsOptions = {
origin: function (origin, callback) {
// Permitir peticiones sin origen (como curl o llamadas del mismo servidor)
// o verificar si el origen entrante está en la lista blanca
if (!origin || whitelist.indexOf(origin) !== -1) {
callback(null, true);
} else {
callback(new Error('Bloqueado por políticas de CORS de la API'));
}
},
credentials: true, // Habilitar soporte para cookies y cabeceras de autorización
optionsSuccessStatus: 200
};
// Aplicar el middleware de CORS con validación dinámica
app.use(cors(corsOptions));
app.get('/api/data', (req, res) => {
res.json({ message: "CORS dinámico configurado con éxito" });
});
app.listen(3000);
Casos de Uso Comunes
Frontend y Backend desacoplados: El caso clásico donde tu aplicación web SPA (ej. React/Vue/Angular) está enhttps://app.mi-dominio.comy necesita consumir la API de datos alojada enhttps://api.mi-dominio.com.
Integraciones externas en widgets: Scripts de chat en vivo, pasarelas de pago incrustadas o widgets que cargan dinámicamente y se comunican con sus respectivos servidores de origen para procesar interacciones del usuario.
CDNs y fuentes personalizadas: Navegadores que cargan tipografías web (.woff2) o archivos de assets estáticos desde servidores web de entrega de contenido (CDNs) independientes.
APIs de datos públicos: Servicios libres (como mapas, clima, divisas) que pretenden ser consumidos de forma abierta en el navegador mediante el comodínAccess-Control-Allow-Origin: *.
Para no morir en el intento y consejos que no pediste
Configurar CORS es una de las mayores fuentes de dolores de cabeza para los desarrolladores. Conocer estos secretos te evitará atascarte en problemas repetitivos:
1. El gran conflicto: Credentials + Wildcard
Si tu aplicación requiere enviar sesiones basadas en cookies o cabeceras HTTP específicas como Authorization, debes habilitar la cabecera Access-Control-Allow-Credentials: true.
Sin embargo, el estándar prohíbe terminantemente combinar credentials con un wildcard (*) en Access-Control-Allow-Origin. Si intentas hacerlo, el navegador bloqueará inmediatamente la respuesta.
- Cómo resolverlo: Tu servidor debe leer dinámicamente el valor del encabezado
Originde la solicitud entrante, comprobar si está incluido en tu lista de dominios seguros autorizados y, en caso positivo, retornar ese dominio específico en la cabeceraAccess-Control-Allow-Origin.
2. Cuida el rendimiento: Configura Access-Control-Max-Age
Por cada petición REST compleja (métodos PUT, DELETE o envíos de application/json), el navegador emite primero un preflight de tipo OPTIONS. Esto duplica la carga en tu API y añade latencia innecesaria en la carga del sitio.
- Cómo resolverlo: Añade la cabecera
Access-Control-Max-Ageindicando los segundos que el navegador puede conservar en caché la aprobación del preflight. Un valor de86400(24 horas) o3600(1 hora) optimiza radicalmente la velocidad de navegación del usuario.
3. La trampa de las pruebas con curl y Postman
Si experimentas un error de CORS en la consola del navegador, no intentes diagnosticarlo usando Postman o curl para ver si la petición falla de la misma manera.
- Cómo resolverlo: CORS es un control del lado del cliente. Los clientes HTTP no integrados en navegadores ignoran por completo estas políticas. Concéntrate en inspeccionar la pestaña Network de las herramientas de desarrollo de tu navegador y confirma las cabeceras inyectadas por el servidor.
Reflexión Final
CORS no es un error de código ni una barrera molesta, sino una protección de primera línea para garantizar la privacidad y los datos de las sesiones de los usuarios en la web abierta. Una correcta comprensión de su flujo de negociación evita vulnerabilidades y optimiza el rendimiento.
Para llevarte a casa:
- CORS protege a tus usuarios, no a tu base de datos de atacantes externos (para eso usa JWT/API Keys).
- Nunca mezcles
Credentialscon comodines*para evitar fallos de seguridad críticos en tu API. - Configura
Access-Control-Max-Ageen producción para evitar duplicar el tráfico de tu backend.
SOCIAL SHARE CARD GENERATOR