Command Palette

Search for a command to run...

CORS: Cross-Origin Resource Sharing en Fetch API

Aprende a manejar CORS en Fetch API, entender la política de mismo origen, configurar peticiones cross-origin y resolver errores comunes.

Lectura: 18 min
Nivel: Intermedio

TL;DR - Resumen rápido

  • CORS es un mecanismo de seguridad que permite peticiones cross-origin controladas
  • Same-Origin Policy restringe peticiones a diferentes orígenes por defecto
  • Las peticiones CORS simples (GET, POST simple) no necesitan preflight
  • Las peticiones CORS complejas (con headers personalizados) necesitan OPTIONS preflight
  • Configura Access-Control-Allow-Origin en el servidor para permitir orígenes específicos

Introducción a CORS

CORS (Cross-Origin Resource Sharing) es un mecanismo de seguridad del navegador que permite o restringe peticiones HTTP cross-origin. Por defecto, los navegadores implementan la Same-Origin Policy, que impide que una página web haga peticiones a un dominio diferente del que la sirvió. CORS relaja esta restricción de forma controlada y segura, permitiendo peticiones cross-origin cuando el servidor lo autoriza explícitamente.

Cuando trabajas con Fetch API, encontrarás CORS frecuentemente, especialmente cuando tu frontend está en un dominio y tu API en otro. Entender cómo funciona CORS es crucial para desarrollar aplicaciones web modernas que consumen APIs externas o microservicios distribuidos en múltiples dominios.

  • <strong>Same-Origin Policy</strong>: Restricción de seguridad por defecto de los navegadores
  • <strong>CORS</strong>: Mecanismo que permite peticiones cross-origin controladas
  • <strong>Origin</strong>: Protocolo, dominio y puerto (ej: https://example.com:443)
  • <strong>Preflight</strong>: Petición OPTIONS previa para verificar permisos
  • <strong>Credenciales</strong>: Cookies, auth headers y TLS client certificates

¿Qué es CORS?

CORS es un estándar W3C que define cómo los navegadores y servidores deben comunicarse para permitir peticiones cross-origin de forma segura. Sin CORS, una página en https://example.com no podría hacer peticiones ahttps://api.example.com. CORS permite que el servidor indique explícitamente qué orígenes pueden acceder a sus recursos y qué métodos y headers están permitidos.

CORS funciona a través de headers HTTP específicos que el servidor envía en la respuesta. El navegador verifica estos headers antes de permitir que el JavaScript acceda a la respuesta. Si los headers no están presentes o no incluyen el origen de la petición, el navegador bloquea el acceso a la respuesta y genera un error CORS.

cors-basico.js
Loading code...

Este ejemplo muestra una petición CORS básica. Cuando haces una petición a un dominio diferente, el navegador envía automáticamente el header Origin con el origen de tu petición. El servidor debe responder con el headerAccess-Control-Allow-Origin que incluya tu origen, o el navegador bloqueará el acceso a la respuesta. Recuerda que el puerto es parte del origen:https://example.com y https://example.com:8080 son orígenes diferentes, por lo que necesitas configurar CORS para cada puerto específico.

Orígenes y Same-Origin Policy

Same-Origin Policy es una restricción de seguridad crítica que implementan todos los navegadores modernos. Esta política define que un origen solo puede acceder a recursos del mismo origen. Dos URLs tienen el mismo origen si tienen el mismo protocolo, dominio y puerto. Cualquier diferencia en estos componentes hace que los orígenes sean diferentes y la política de seguridad se aplique.

  • <strong>Mismo origen</strong>: https://example.com y https://example.com/usuarios
  • <strong>Diferente protocolo</strong>: http://example.com y https://example.com
  • <strong>Diferente dominio</strong>: https://example.com y https://api.example.com
  • <strong>Diferente puerto</strong>: https://example.com y https://example.com:8080
  • <strong>Subdominios</strong>: https://example.com y https://sub.example.com son orígenes diferentes
same-origin-policy.js
Loading code...

Este ejemplo muestra cómo Same-Origin Policy afecta las peticiones. Las peticiones al mismo origen funcionan sin restricciones, mientras que las peticiones a orígenes diferentes requieren CORS. Es importante entender esto porque los errores de CORS pueden ser confusos si no comprendes la política de mismo origen.

File:// y CORS

Los archivos abiertos con el protocolo file:// tienen un origen único y nulo. Las peticiones desde file:// a cualquier servidor siempre requieren CORS, pero muchos navegadores bloquean estas peticiones por seguridad. Para desarrollo local, usa un servidor HTTP local en lugar de abrir archivos directamente.

Solicitud CORS

Las peticiones CORS se dividen en dos categorías: simples y complejas. Las peticiones CORS simples son peticiones GET, HEAD o POST con ciertos tipos de contenido que no disparan una petición preflight. Las peticiones CORS complejas son peticiones que tienen headers personalizados o usan métodos distintos de GET, HEAD, POST simple, y requieren una petición OPTIONS previa para verificar permisos.

cors-simple.js
Loading code...

Este ejemplo muestra una petición CORS simple. Las peticiones simples no requieren preflight y el navegador hace la petición directamente. El servidor responde con los headers CORS necesarios y el navegador permite el acceso a la respuesta. Las peticiones simples son más eficientes porque evitan la petición OPTIONS adicional.

cors-compleja.js
Loading code...

Este ejemplo muestra una petición CORS compleja. Las peticiones complejas requieren preflight porque tienen headers personalizados. El navegador primero hace una petición OPTIONS para verificar si el servidor permite el método y headers que deseas usar. Si el servidor responde afirmativamente, el navegador procede con la petición real.

Headers que disparan preflight

Los siguientes headers disparan una petición preflight: Authorization,Content-Type (excepto form-data, url-encoded, text/plain), y cualquier header personalizado que comience con X-. Si tu petición incluye estos headers, el navegador hará automáticamente una petición OPTIONS previa.

Preflight OPTIONS

El preflight es una petición OPTIONS que el navegador hace automáticamente antes de una petición CORS compleja. Esta petición verifica si el servidor permite el método HTTP, los headers y el origen de la petición real. El servidor responde con headers que indican qué está permitido, y el navegador solo procede con la petición real si el preflight fue exitoso.

preflight-options.js
Loading code...

Este ejemplo muestra cómo funciona el preflight. Cuando haces una petición CORS compleja, el navegador primero hace una petición OPTIONS con el mismo origen, método y headers. El servidor responde con headers CORS: Access-Control-Allow-Origin (orígenes permitidos), Access-Control-Allow-Methods (métodos HTTP permitidos),Access-Control-Allow-Headers (headers permitidos en la petición),Access-Control-Max-Age (cuánto tiempo cachear el resultado preflight), yAccess-Control-Allow-Credentials (si se permiten credenciales). Si el servidor no permite la petición, el navegador bloquea la petición real y genera un error CORS. Ten en cuenta que las peticiones preflight añaden latencia adicional porque requieren dos peticiones HTTP (OPTIONS + la petición real), por lo que es recomendable usar peticiones CORS simples cuando sea posible.

Credenciales y CORS

Por defecto, CORS no permite enviar credenciales (cookies, headers de autenticación, certificados TLS del cliente) en peticiones cross-origin. Esto es una restricción de seguridad para evitar que sitios maliciosos accedan a recursos protegidos con credenciales del usuario. Para enviar credenciales en peticiones CORS, debes configurar tanto el cliente como el servidor explícitamente.

cors-credenciales.js
Loading code...

Este ejemplo muestra cómo enviar credenciales en una petición CORS. En el cliente, debes especificar credentials: 'include' para que el navegador envíe cookies y headers de autenticación. En el servidor, debes incluir el headerAccess-Control-Allow-Credentials: true y especificar el origen exacto (no puedes usar * cuando envías credenciales).

cors-with-cookies.js
Loading code...

Este ejemplo muestra cómo enviar cookies en una petición CORS. Las cookies son un tipo común de credenciales que se usan para mantener sesiones de usuario. Para que el navegador envíe cookies en peticiones cross-origin, debes especificar credentials: 'include'y configurar el servidor para aceptar credenciales del origen específico.

Credenciales y *

Cuando envías credenciales (credentials: 'include'), no puedes usarAccess-Control-Allow-Origin: * en el servidor. Debes especificar el origen exacto (ej: https://example.com). Usar * con credenciales causará un error CORS.

Configurar CORS en el Servidor

Configurar CORS en el servidor es esencial para permitir peticiones cross-origin desde tu frontend. La configuración varía según el lenguaje y framework que uses, pero el principio es el mismo: debes incluir los headers CORS apropiados en las respuestas del servidor. Estos headers indican al navegador qué orígenes, métodos y headers están permitidos.

cors-server-nodejs.js
Loading code...

Este ejemplo muestra cómo configurar CORS en un servidor Node.js con Express. El middleware cors simplifica la configuración y maneja automáticamente los headers CORS necesarios. Puedes configurar qué orígenes permitir, qué métodos aceptar, y si permitir credenciales. Para producción, especifica los orígenes exactos en lugar de usar *.

cors-server-manual.js
Loading code...

Este ejemplo muestra cómo configurar CORS manualmente sin middleware. Configurar CORS manualmente te da más control pero requiere más código. Debes incluir los headersAccess-Control-Allow-Origin, Access-Control-Allow-Methods, yAccess-Control-Allow-Headers en las respuestas a las peticiones OPTIONS y a las peticiones reales.

CORS en producción

En producción, evita usar Access-Control-Allow-Origin: * porque permite cualquier origen acceder a tu API. Especifica los orígenes exactos que necesitas permitir (ej: https://example.com, https://www.example.com). Esto mejora la seguridad de tu aplicación y previene accesos no autorizados.

Errores Comunes de CORS

Los errores de CORS son comunes cuando desarrollas aplicaciones web que consumen APIs externas. El error más frecuente es "No 'Access-Control-Allow-Origin' header is present on the requested resource", que ocurre cuando el servidor no configura CORS correctamente. Otros errores comunes incluyen problemas con credenciales, headers personalizados no permitidos, y métodos HTTP no autorizados.

error-cors-faltante.js
Loading code...

Este ejemplo muestra el error CORS más común: el servidor no incluye el headerAccess-Control-Allow-Origin. Cuando esto ocurre, el navegador bloquea el acceso a la respuesta y genera un error CORS. La solución es configurar CORS en el servidor para incluir este header con el origen de tu petición.

error-cors-credenciales.js
Loading code...

Este ejemplo muestra un error CORS con credenciales. Cuando envías credenciales (credentials: 'include') y el servidor usa Access-Control-Allow-Origin: *, el navegador bloquea la petición. La solución es especificar el origen exacto en el servidor en lugar de usar el wildcard.

error-cors-headers.js
Loading code...

Este ejemplo muestra un error CORS con headers personalizados. Cuando envías headers personalizados que el servidor no permitió, el navegador bloquea la petición. La solución es incluir los headers permitidos en Access-Control-Allow-Headers en el servidor.

Debugging CORS

Para debugging errores CORS, usa las DevTools del navegador. En la pestaña Network, busca la petición fallida y verifica los headers de la respuesta. El error CORS aparecerá en la consola con detalles sobre qué header faltó o qué restricción se violó. También puedes usar herramientas como curl para verificar los headers del servidor directamente.

Resumen: CORS en Fetch API

Conceptos principales:

  • CORS es un mecanismo de seguridad para peticiones cross-origin controladas
  • Same-Origin Policy restringe peticiones a diferentes orígenes por defecto
  • Las peticiones CORS simples (GET, POST simple) no necesitan preflight
  • Las peticiones CORS complejas (con headers personalizados) necesitan OPTIONS preflight
  • Configura Access-Control-Allow-Origin en el servidor para permitir orígenes específicos

Mejores prácticas:

  • Especifica orígenes exactos en producción, no uses el wildcard *
  • Usa credentials: 'include' solo cuando realmente necesites enviar credenciales
  • Minimiza el uso de headers personalizados para evitar preflight innecesario
  • Configura Access-Control-Allow-Methods y Access-Control-Allow-Headers explícitamente
  • Usa middleware CORS de tu framework para simplificar la configuración