Funcionamiento de CORS - Comprendiendo las Peticiones Cross-Origin

13 min de lectura | 2025.12.10

¿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:443 y https://api.example.com:443 son 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

HeaderDescripción
Access-Control-Allow-OriginOrigen permitido
Access-Control-Allow-MethodsMétodos HTTP permitidos
Access-Control-Allow-HeadersHeaders de petición permitidos
Access-Control-Allow-CredentialsPermitir envío de cookies
Access-Control-Expose-HeadersHeaders accesibles desde JS
Access-Control-Max-AgeTiempo 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