CORS Security: Configuración Segura de Cross-Origin Resource Sharing
Aprende a configurar CORS de forma segura para compartir recursos entre diferentes orígenes sin comprometer la seguridad de tu aplicación.
TL;DR - Resumen rápido
- CORS es un mecanismo de seguridad que permite o restringe solicitudes cross-origin
- Las políticas de Same-Origin Policy protegen contra ataques CSRF y XSS
- Configura orígenes permitidos explícitamente, no uses comodín '*' en producción
- Usa credenciales con precaución: solo con orígenes confiables y HTTPS
- Valida y sanitiza todos los headers personalizados de CORS
Introducción a CORS
CORS (Cross-Origin Resource Sharing) es un mecanismo de seguridad basado en headers HTTP como Access-Control-Allow-Origin, Access-Control-Allow-Methods y Access-Control-Allow-Headers que permite a los servidores controlar qué orígenes pueden acceder a sus recursos. Sin CORS, la Same-Origin Policy bloquearía todas las solicitudes entre dominios diferentes.
Un origen se define como protocolo://dominio:puerto (ejemplo: https://api.ejemplo.com:443). Dos URLs tienen el mismo origen solo si comparten exactamente protocolo, dominio y puerto. https://app.com y http://app.com son orígenes diferentes (protocolo distinto), así como https://api.com y https://app.com (dominio distinto).
Same-Origin Policy vs CORS
La Same-Origin Policy (SOP) es la regla de seguridad por defecto que bloquea solicitudes entre orígenes diferentes. CORS es un mecanismo que permite relajar la SOP de forma controlada y segura. SOP protege por defecto, CORS permite excepciones específicas cuando se configuran correctamente.
Cómo Funciona CORS
CORS funciona mediante headers HTTP que el servidor envía en sus respuestas: Access-Control-Allow-Origin especifica qué orígenes pueden acceder, Access-Control-Allow-Methods define los métodos HTTP permitidos (GET, POST, PUT, DELETE), y Access-Control-Allow-Headers indica qué headers personalizados acepta el servidor. Hay dos tipos de solicitudes CORS: simples y preflight.
Solicitudes Simples
Las solicitudes simples usan métodos GET, HEAD o POST con Content-Type de application/x-www-form-urlencoded, multipart/form-data o text/plain. Estas solicitudes se envían directamente al servidor sin preflight, y el navegador automáticamente agrega el header Origin: https://frontend.ejemplo.com para que el servidor pueda verificarlo.
Este ejemplo muestra una solicitud CORS simple. El navegador envía la solicitud directamente y el servidor responde con el header Access-Control-Allow-Origin. Si el origen del navegador coincide con este header, la respuesta se entrega al JavaScript.
Solicitudes Preflight (OPTIONS)
Las solicitudes preflight envían OPTIONS antes de solicitudes complejas (PUT, DELETE, PATCH o POST con application/json). El navegador envía Access-Control-Request-Method: PUT y Access-Control-Request-Headers: Content-Type, y el servidor responde con Access-Control-Allow-Methods, Access-Control-Allow-Headers y Access-Control-Max-Age: 86400 para cachear el resultado.
Este ejemplo muestra una solicitud preflight. El navegador primero envía una solicitud OPTIONS para verificar si la solicitud POST con el header personalizado está permitida. El servidor responde con los headers de CORS apropiados.
Cuándo ocurre Preflight
Las solicitudes preflight ocurren cuando: usas métodos como PUT, DELETE, PATCH; envías headers personalizados; usas content-type diferente a application/x-www-form-urlencoded, multipart/form-data, o text/plain; o usas credenciales con ciertos métodos.
Configuración de CORS
Configurar CORS correctamente es esencial para la seguridad. Una configuración incorrecta como origin: '*' con credentials: true es inválida y permite que cualquier sitio acceda a tu API, exponiendo tu aplicación a ataques CSRF y robo de datos. Siempre especifica orígenes exactos en producción.
Configuración en Express.js
Express.js proporciona el middleware cors para configuración fácil. Usa app.use(cors({ origin: 'https://frontend.ejemplo.com', methods: ['GET', 'POST'], credentials: true })) para especificar orígenes permitidos, métodos HTTP, y si acepta cookies. Configura maxAge: 86400 para cachear resultados de preflight por 24 horas.
Este ejemplo muestra cómo configurar CORS en Express.js. La configuración especifica orígenes permitidos, métodos HTTP permitidos, headers permitidos, y si se permiten credenciales.
Configuración de Orígenes
La configuración de orígenes controla el acceso a tu API. Usa origin: 'https://frontend.ejemplo.com' para un solo origen, origin: ['https://frontend.com', 'https://app.com'] para múltiples, o origin: (origin, callback) => { callback(null, allowedOrigins.includes(origin)) } para validación dinámica. Evita origin: '*' en producción con datos sensibles.
Este ejemplo muestra diferentes configuraciones de orígenes. Puedes especificar un solo origen, múltiples orígenes, o usar una función para validar orígenes dinámicamente.
Advertencia: Nunca uses '*' con credenciales
Nunca configures Access-Control-Allow-Origin: '*' junto con Access-Control-Allow-Credentials: true. Esta combinación es inválida y los navegadores bloquearán la solicitud. Si necesitas credenciales, debes especificar orígenes exactos.
Prácticas de CORS Seguro
Para maximizar la seguridad, especifica siempre orígenes exactos con origin: ['https://app.com'], limita métodos con methods: ['GET', 'POST'], valida headers personalizados antes de procesarlos, y usa credentials: true solo con orígenes confiables y HTTPS. En producción, verifica que todos los orígenes usen https:// para proteger datos sensibles.
- Especifica orígenes permitidos explícitamente, nunca uses '*' en producción
- Usa HTTPS para todos los orígenes permitidos en producción
- Limita los métodos HTTP permitidos solo a los que realmente necesitas
- Valida headers personalizados antes de procesarlos en tu aplicación
- Usa credenciales solo cuando sea absolutamente necesario
Este ejemplo muestra una configuración de CORS segura con orígenes específicos, métodos limitados, y validación de headers personalizados.
Resumen: CORS Security
Conceptos principales:
- •CORS permite solicitudes cross-origin de forma controlada y segura
- •Same-Origin Policy bloquea solicitudes entre orígenes diferentes por defecto
- •Las solicitudes simples no requieren preflight, las complejas sí
- •Preflight (OPTIONS) verifica permisos antes de la solicitud real
- •Los headers de CORS controlan orígenes, métodos y headers permitidos
Mejores prácticas:
- •Especifica orígenes permitidos explícitamente, evita '*' en producción
- •Usa HTTPS para todos los orígenes permitidos en producción
- •Limita métodos HTTP a los que realmente necesitas (GET, POST, etc.)
- •Valida headers personalizados antes de procesarlos
- •Usa credenciales solo con orígenes confiables y cuando sea necesario