CORS

Estandares Y Rfcs Security Notes Jan 6, 2025 JAVASCRIPT
security browser http-headers web

Definition

Imagina que estas en una fiesta en casa y quieres pedir azucar prestada al vecino de al lado. En el mundo fisico, simplemente irias y pedirias. Pero en el mundo de los navegadores web, hay un guardia de seguridad parado entre cada sitio web, y por defecto, ese guardia dice “no” a todas las peticiones entre propiedades. CORS (Cross-Origin Resource Sharing o Intercambio de Recursos de Origen Cruzado) es el sistema que permite al vecino ponerte en una lista de invitados aprobados para que el guardia de seguridad deje pasar tu peticion.

Cuando visitas un sitio web, tu navegador aplica limites estrictos sobre lo que ese sitio puede hacer. Especificamente, previene que JavaScript en un sitio web haga peticiones a un sitio web diferente - esto se llama “politica del mismo origen” y es una caracteristica de seguridad fundamental. Sin ella, un sitio web malicioso podria hacer peticiones a tu banco usando tu sesion iniciada. Pero esto crea un problema: las aplicaciones legitimas a menudo necesitan hacer peticiones de origen cruzado. Tu frontend en app.miempresa.com podria necesitar datos de una API en api.miempresa.com. CORS resuelve esto proporcionando una forma estandarizada para que los servidores digan “Confio en peticiones de estos origenes especificos”.

Asi es como funciona: cuando tu navegador hace una peticion de origen cruzado, incluye un header Origin diciendo de donde viene la peticion. El servidor puede entonces responder con headers como Access-Control-Allow-Origin para indicar si permite ese origen. Si el servidor dice que si, el navegador permite que JavaScript vea la respuesta. Si no, el navegador la bloquea - no porque la peticion fallo, sino porque el navegador te esta protegiendo. La peticion podria realmente tener exito en el lado del servidor, pero el navegador no dejara que tu JavaScript acceda al resultado.

Example

Escenario Real 1: Arquitectura de Aplicacion de Pagina Unica Estas construyendo una app React alojada en www.mitienda.com que necesita obtener datos de productos de tu API en api.mitienda.com. Aunque ambos son “tus” dominios, el navegador los ve como origenes diferentes. Sin CORS configurado en tu servidor API, tu app React seria bloqueada de leer respuestas. La API necesita responder con Access-Control-Allow-Origin: https://www.mitienda.com para permitirlo.

Escenario Real 2: Integracion con API de Terceros Tu sitio web quiere mostrar datos del clima de una API publica del tiempo. Cuando tu JavaScript intenta hacer fetch de api.clima.com, el navegador primero verifica si esa API permite tu origen. Las APIs publicas tipicamente establecen Access-Control-Allow-Origin: * para permitir peticiones desde cualquier sitio web. Pero si quieren restringir acceso a clientes de pago, podrian solo permitir origenes especificos.

Escenario Real 3: Google Fonts y Recursos CDN Cuando incluyes Google Fonts en tu sitio web, tu navegador hace peticiones a fonts.googleapis.com. Los servidores de Google incluyen headers CORS que permiten a cualquier origen acceder a archivos de fuentes. Por eso puedes usar Google Fonts desde cualquier sitio web - su politica CORS lo permite explicitamente.

Escenario Real 4: Peticiones Preflight para Operaciones Complejas Tu app necesita enviar una peticion POST con datos JSON y headers personalizados a una API. Antes de enviar la peticion real, el navegador automaticamente envia una peticion “preflight” OPTIONS preguntando “Esta permitido este tipo especifico de peticion?” El servidor debe responder diciendo que metodos y headers acepta. Solo entonces el navegador enviara tu peticion real. Este proceso de dos pasos ocurre automaticamente para cualquier cosa mas alla de simples peticiones GET.

Analogia

El Sistema de Visas de Embajada: Obtener datos de otro origen es como necesitar una visa para entrar a otro pais. La politica del mismo origen es como requerir visa para todos los visitantes extranjeros. CORS es el sistema donde el pais de destino (servidor) publica una lista de que paises (origenes) pueden entrar y que pueden hacer (metodos, headers). El control fronterizo (navegador) verifica esta lista antes de dejar pasar la peticion.

La Lista de Invitados del Club Nocturno: Imagina un club nocturno (servidor API) donde el portero (navegador) solo deja entrar a personas en la lista de invitados. El dueno del club ha puesto ciertos nombres en la lista aprobada (origenes permitidos). Cuando tu (la peticion) llegas diciendo ser de un sitio web especifico, el portero verifica la lista. Si estas en ella, entras. CORS es el sistema de lista de invitados.

El Interfono del Edificio de Apartamentos: En un edificio de apartamentos seguro, los visitantes no pueden simplemente entrar. Usan el interfono para llamar a un apartamento especifico. El residente (servidor) puede entonces dejarlos pasar (permitir la peticion) o no. CORS es como este sistema - el servidor decide quien entra basandose en de donde vienen.

La Sala de Eventos Privados del Restaurante: Un restaurante tiene una sala de eventos privados. Normalmente, solo las personas que organizan el evento pueden invitar invitados. Pero el restaurante puede pre-autorizar a ciertas otras fiestas a enviar invitados. Los headers CORS son como esta pre-autorizacion - el servidor esta diciendo al navegador “si, esta bien que este sitio web especifico envie peticiones aqui”.

Code Example


// Headers CORS en respuesta API
[HTTP/1.1](https://reference.apios.info/es/terms/http-1-1/) 200 OK
Access-Control-Allow-Origin: https://myapp.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 3600

// Peticion preflight (OPTIONS)
OPTIONS /api/users HTTP/1.1
Origin: https://myapp.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type

// Configuracion del servidor (Express.js)
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', 'https://myapp.com');
  res.header('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE');
  res.header('Access-Control-Allow-Headers', 'Content-Type,Authorization');
  next();
});

Diagram

sequenceDiagram
participant Browser
participant API
Note over Browser,API: Peticion Simple
Browser->>API: GET /data + header Origin
API->>Browser: 200 OK + headers CORS
Note over Browser,API: Peticion Preflight
Browser->>API: OPTIONS /data
API->>Browser: 204 + Metodos permitidos
Browser->>API: POST /data
API->>Browser: 201 Created

Notas de Seguridad

SECURITY NOTES

Requisitos Principales:

  • Nunca uses Access-Control-Allow-Origin: * con credenciales.
  • Siempre especifica origenes exactos.
  • Valida el header Origin del lado del servidor.

Mejores Prácticas:

  • Ten cuidado con Access-Control-Allow-Headers - solo permite headers necesarios.
  • Limita Access-Control-Max-Age para prevenir politicas CORS obsoletas.
  • CORS NO es un sustituto de autenticacion apropiada - solo controla acceso del navegador, no peticiones HTTP directas..

Mejores Practicas

  1. Nunca uses Access-Control-Allow-Origin: * con credenciales
  2. Especifica origenes exactos en lugar de comodines en produccion
  3. Valida el header Origin del lado del servidor
  4. Solo expone headers necesarios con Access-Control-Expose-Headers
  5. Establece Access-Control-Max-Age apropiado para cachear respuestas preflight
  6. Usa middleware/librerias CORS en lugar de establecer headers manualmente

Errores Comunes

Usar Access-Control-Allow-Origin: * con credenciales (falla silenciosamente), no manejar peticiones preflight OPTIONS, exponer demasiados headers, establecer max-age muy largo para cache preflight, confundir CORS con seguridad del servidor (CORS solo restringe navegadores, no curl/Postman), olvidar incluir Origin en header Vary.

Standards & RFCs