Que es CORS?

Posted on April 20, 2026
Profile
Gastón Gaitan
April 20, 2026 · 13 hours, 23 minutes ago
Que es CORS?

CORS: que es, por que existe y como configurarlo

El problema: Same-Origin Policy

Los navegadores implementan una politica de seguridad llamada Same-Origin Policy. Esta regla dice que una pagina web solo puede hacer requests al mismo dominio desde el que fue cargada.

Dos URLs tienen el mismo origen si comparten el mismo protocolo, dominio y puerto.

URL de la pagina URL del request Mismo origen?
https://miapp.com https://miapp.com/api/datos Si
https://miapp.com https://api.miapp.com/datos No (distinto subdominio)
https://miapp.com http://miapp.com/api/datos No (distinto protocolo)
https://miapp.com https://otra-app.com/api No (distinto dominio)

Si el origen no coincide, el navegador bloquea el request. Esto protege a los usuarios, pero tambien genera un problema: muchas aplicaciones modernas necesitan que el frontend y la API esten en dominios distintos.

La solucion: CORS

CORS (Cross-Origin Resource Sharing) es un mecanismo que permite a una API indicarle al navegador: "esta bien, acepto requests desde este otro dominio".

Funciona a traves de headers HTTP que la API incluye en sus respuestas. El mas importante es Access-Control-Allow-Origin.

Diagrama de flujo CORS mostrando la comunicacion entre navegador y servidor
Navegador
miapp.com
API
api.miapp.com
Respuesta con
Allow-Origin header
Navegador
permite la respuesta

Si la API no incluye el header o el origen no coincide, el navegador descarta la respuesta y muestra un error de CORS en la consola.

Navegador
sitio-malicioso.com
API
api.miapp.com
Sin header
Allow-Origin
Navegador
bloquea la respuesta

El preflight request

Antes de enviar ciertos requests (POST con JSON, requests con headers custom, etc.), el navegador envia automaticamente un request OPTIONS llamado preflight. Es como preguntar "puedo enviar este request?".

La API responde con los headers CORS indicando que origenes, metodos y headers acepta. Si todo coincide, el navegador procede con el request real.

# El navegador envia automaticamente:
OPTIONS /api/datos HTTP/1.1
Origin: https://miapp.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type

# La API responde:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://miapp.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Credentials: true

Los headers CORS principales

Header Que hace
Access-Control-Allow-Origin Indica que origenes pueden acceder a la API
Access-Control-Allow-Methods Que metodos HTTP estan permitidos (GET, POST, etc.)
Access-Control-Allow-Headers Que headers custom puede enviar el cliente
Access-Control-Allow-Credentials Si se permiten cookies/tokens en el request
Access-Control-Max-Age Cuanto tiempo (en segundos) cachear el resultado del preflight

Ejemplo practico: configurar CORS en FastAPI

FastAPI usa el CORSMiddleware de Starlette para manejar CORS. La configuracion basica se ve asi:

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://miapp.com"],
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "DELETE"],
    allow_headers=["*"],
)

Con esta configuracion, solo https://miapp.com puede hacer requests a la API. Cualquier otro origen es rechazado.

El error comun: allow_origins=["*"]

No hagas esto en produccion:
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],          # Acepta CUALQUIER origen
    allow_credentials=True,  # Con cookies/tokens incluidos
    allow_methods=["*"],
    allow_headers=["*"],
)

Usar ["*"] como origenes permitidos le dice al navegador que cualquier sitio web del mundo puede hacer requests a tu API. Combinado con allow_credentials=True, un sitio malicioso podria ejecutar JavaScript que haga requests usando la sesion activa de un usuario autenticado.

Esto abre la puerta a:

  • CSRF (Cross-Site Request Forgery): un atacante ejecuta acciones en nombre del usuario
  • Robo de datos: un script malicioso lee respuestas de tu API con las credenciales del usuario
  • Explotacion remota: cualquier vulnerabilidad de tu API puede ser explotada desde cualquier sitio

La forma correcta: origenes por entorno

La buena practica es definir exactamente que dominios estan permitidos en cada entorno. En desarrollo necesitas localhost, en produccion solo tu dominio real.

ALLOWED_ORIGINS_BY_ENVIRONMENT = {
    "local": [
        "http://localhost:4200",
        "http://127.0.0.1:4200",
    ],
    "dev": [
        "https://dev.miapp.com",
    ],
    "production": [
        "https://miapp.com",
    ],
}

app.add_middleware(
    CORSMiddleware,
    allow_origins=ALLOWED_ORIGINS_BY_ENVIRONMENT.get(ENVIRONMENT, []),
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "DELETE"],
    allow_headers=["*"],
)

Si el entorno no esta en el diccionario, .get(ENVIRONMENT, []) devuelve una lista vacia, lo que rechaza todos los origenes. Seguro por defecto.

Como verificar que funciona

Podes testear CORS con un simple curl simulando un preflight request:

Origen permitido

curl -i -X OPTIONS https://miapp.com/api/health \
  -H "Origin: https://miapp.com" \
  -H "Access-Control-Request-Method: GET"
Resultado esperado: la respuesta incluye access-control-allow-origin: https://miapp.com

Origen no permitido

curl -i -X OPTIONS https://miapp.com/api/health \
  -H "Origin: https://sitio-malicioso.com" \
  -H "Access-Control-Request-Method: GET"
Resultado esperado: la respuesta NO incluye el header access-control-allow-origin, o devuelve un error 400.

Resumen

Concepto Descripcion
Same-Origin Policy El navegador bloquea requests a dominios distintos por defecto
CORS Mecanismo que permite a la API declarar que origenes acepta
Preflight (OPTIONS) Request automatico del navegador para verificar permisos antes del request real
allow_origins=["*"] Acepta cualquier origen. No usar en produccion
Origenes por entorno Cada entorno solo acepta su propio dominio. Seguro por defecto

Conclusion

CORS no es algo que "hay que resolver para que funcione el frontend". Es una capa de seguridad del navegador que protege a tus usuarios. Configurar ["*"] es desactivar esa proteccion.

La configuracion correcta es explicita: cada entorno declara exactamente que dominios puede aceptar. Es un cambio simple que cierra una superficie de ataque importante.