¿Qué es CORS?
CORS (Cross-Origin Resource Sharing) es un mecanismo del navegador para compartir recursos de forma segura entre diferentes orígenes. Por razones de seguridad, los navegadores restringen por defecto las peticiones a orígenes diferentes.
¿Qué es un origen? Es la combinación de esquema (http/https), host y puerto.
https://example.com:443yhttps://api.example.com:443son orígenes diferentes.
Política del Mismo Origen
Los navegadores restringen las peticiones a diferentes orígenes mediante la Política del Mismo Origen (SOP: Same-Origin Policy).
Desde https://app.example.com:
✓ https://app.example.com/api (mismo origen)
✗ https://api.example.com/v1 (host diferente)
✗ http://app.example.com/api (esquema diferente)
✗ https://app.example.com:8080 (puerto diferente)
Flujo Básico de CORS
Petición Simple
Las peticiones que cumplen las siguientes condiciones se envían sin preflight.
- Métodos: GET, HEAD, POST
- Headers: Accept, Accept-Language, Content-Language, Content-Type (solo algunos)
- Content-Type: application/x-www-form-urlencoded, multipart/form-data, text/plain
Navegador → Servidor:
GET /api/users
Origin: https://app.example.com
Servidor → Navegador:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://app.example.com
Petición Preflight
Las peticiones que no cumplen las condiciones, como headers personalizados o envío de JSON, requieren verificación previa.
1. Preflight (verificación previa)
Navegador → Servidor:
OPTIONS /api/users
Origin: https://app.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type, Authorization
Servidor → Navegador:
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400
2. Petición real
Navegador → Servidor:
POST /api/users
Origin: https://app.example.com
Content-Type: application/json
Authorization: Bearer token123
Headers CORS
Headers de Respuesta
| Header | Descripción |
|---|---|
| Access-Control-Allow-Origin | Origen permitido |
| Access-Control-Allow-Methods | Métodos HTTP permitidos |
| Access-Control-Allow-Headers | Headers de petición permitidos |
| Access-Control-Allow-Credentials | Permitir envío de cookies |
| Access-Control-Expose-Headers | Headers accesibles desde JS |
| Access-Control-Max-Age | Tiempo de caché del resultado preflight |
Ejemplo de Configuración (Express.js)
const cors = require('cors');
// Permitir origen específico
app.use(cors({
origin: 'https://app.example.com',
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true,
maxAge: 86400
}));
// Permitir múltiples orígenes
app.use(cors({
origin: ['https://app.example.com', 'https://admin.example.com'],
}));
// Validar origen dinámicamente
app.use(cors({
origin: (origin, callback) => {
const allowedOrigins = ['https://app.example.com'];
if (!origin || allowedOrigins.includes(origin)) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
}
}));
Modo Credentials
Las peticiones que incluyen cookies o información de autenticación requieren configuración especial.
// Lado del cliente
fetch('https://api.example.com/data', {
credentials: 'include' // Incluir cookies
});
// Lado del servidor
// Access-Control-Allow-Origin: * no se puede usar
// Se debe especificar un origen concreto
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Credentials: true
Errores Comunes y Soluciones
Error 1: No ‘Access-Control-Allow-Origin’ header
Causa: El servidor no está devolviendo headers CORS
Solución:
- Configurar CORS en el lado del servidor
- Enviar petición a través de un proxy
Error 2: Wildcard with credentials
Causa: Combinación de credentials: 'include' con
Access-Control-Allow-Origin: *
Solución:
- Especificar un origen concreto
Access-Control-Allow-Origin: https://app.example.com
Error 3: Method not allowed
Causa: El método no está permitido en el preflight
Solución:
- Añadir el método necesario a Access-Control-Allow-Methods
Error 4: Header not allowed
Causa: El header personalizado no está permitido
Solución:
- Añadir el header a Access-Control-Allow-Headers
Soluciones CORS en Desarrollo
Usar Proxy
// Ejemplo de configuración de Vite
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'https://api.example.com',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
});
Extensiones del Navegador
Existen extensiones que deshabilitan CORS solo en desarrollo, pero no las uses en producción.
Consideraciones de Seguridad
Peligro del Wildcard
✗ Peligroso: Permite todos los orígenes
Access-Control-Allow-Origin: *
✓ Recomendado: Especificar orígenes permitidos explícitamente
Access-Control-Allow-Origin: https://app.example.com
Validación de Origen
// ✗ Mal ejemplo: Devolver el Origin de la petición tal cual
res.setHeader('Access-Control-Allow-Origin', req.headers.origin);
// ✓ Buen ejemplo: Validar con lista blanca
const allowedOrigins = ['https://app.example.com'];
if (allowedOrigins.includes(req.headers.origin)) {
res.setHeader('Access-Control-Allow-Origin', req.headers.origin);
}
Resumen
CORS es un mecanismo importante que permite compartir recursos entre diferentes orígenes mientras mantiene la seguridad de las aplicaciones web. Con una configuración adecuada de headers y validación de orígenes, puedes lograr comunicación cross-origin segura.
← Volver a la lista