CORS para principiantes

¿Qué es CORS? Entender cómo hacer llamadas a API's externas para no tener el error CORS en el navegador.

cors

¿Qué significa CORS?

CORS es el acrónimo de Cross-Origin Resource Sharing o uso compartido de recursos entre orígenes. Es un mecanismo de seguridad implementado en los navegadores que permite a un servidor indicar qué orígenes (dominios) tienen permiso para acceder a sus recursos.

Por defecto, los navegadores aplican una política de seguridad conocida como Same-Origin Policy (Política del Mismo Origen). Esta política restringe el acceso a recursos de un servidor desde un dominio diferente para evitar ataques como la falsificación de solicitudes entre sitios (Cross-Site Request Forgery, CSRF) o el robo de credenciales. Sin embargo, hay escenarios válidos donde se necesita compartir recursos entre diferentes orígenes, y es ahí donde entra en juego CORS.

¿Cómo funciona CORS?

Cuando un cliente (como un navegador) realiza una solicitud HTTP a un servidor que pertenece a otro dominio, el servidor puede responder con cabeceras específicas que indican si la solicitud está permitida o no. Estas cabeceras son las siguientes:

  • Access-Control-Allow-Origin: Especifica los dominios permitidos para acceder a los recursos del servidor. Por ejemplo:

    Access-Control-Allow-Origin: https://example.com

    También puede usarse el asterisco (*) para permitir el acceso desde cualquier dominio, aunque esta práctica no es recomendada por razones de seguridad.

  • Access-Control-Allow-Methods: Indica los métodos HTTP permitidos (GET, POST, PUT, DELETE, etc.). Por ejemplo:

    Access-Control-Allow-Methods: GET, POST
  • Access-Control-Allow-Headers: Especifica qué cabeceras personalizadas pueden ser enviadas en la solicitud.

  • Access-Control-Allow-Credentials: Permite compartir cookies o credenciales entre orígenes si se establece en true.

Cuando el navegador recibe estas cabeceras, decide si permite o bloquea la solicitud, garantizando así que sólo los orígenes autorizados accedan a los recursos.

Solicitudes Preflight

Algunas solicitudes, conocidas como “solicitudes simples”, no requieren una verificación previa y se envían directamente. Estas solicitudes incluyen métodos como GET o POST con tipos de contenido básicos (ej., application/x-www-form-urlencoded).

Sin embargo, otras solicitudes más complejas (como las que usan métodos PUT o DELETE, o cabeceras personalizadas) requieren un paso adicional llamado preflight. El navegador primero envía una solicitud de tipo OPTIONS al servidor para comprobar si la operación está permitida. Si el servidor responde afirmativamente con las cabeceras correctas, el navegador procede con la solicitud principal.

Ejemplo de una solicitud preflight:

Solicitud OPTIONS enviada por el navegador:

OPTIONS /api/resource HTTP/1.1
Host: api.example.com
Origin: https://myfrontend.com
Access-Control-Request-Method: DELETE
Access-Control-Request-Headers: Authorization

Respuesta del servidor:

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://myfrontend.com
Access-Control-Allow-Methods: DELETE
Access-Control-Allow-Headers: Authorization

Si el servidor no responde adecuadamente, la solicitud principal no se enviará y el navegador bloqueará el acceso.

¿Cómo prevenir ataques relacionados con CORS?

1. Same-Origin Policy

Antes de implementar CORS, es importante evaluar si la aplicación realmente necesita permitir solicitudes desde dominios externos. Si todos los recursos pueden permanecer dentro del mismo dominio, es preferible aprovechar la Same-Origin Policy como medida de seguridad predeterminada.

2. Configuración estricta de cabeceras

Configura las cabeceras de CORS de manera estricta:

  • Especifica dominios específicos en lugar de usar * en Access-Control-Allow-Origin.
  • Limita los métodos permitidos a los estrictamente necesarios.
  • Define qué cabeceras personalizadas pueden enviarse.
  • Permite el uso de credenciales sólo cuando sea necesario y está seguro de que los orígenes autorizados son confiables.

3. Validación en el lado del servidor

No confíes exclusivamente en las cabeceras CORS para la seguridad. Asegúrate de validar y autenticar cada solicitud en el servidor para proteger los datos sensibles y evitar accesos no autorizados.

Ejemplo práctico

Imagina que tienes un servidor API en https://api.example.com y una aplicación frontend en https://frontend.example.com. Para permitir que el frontend acceda a la API, puedes configurar CORS en el servidor de la siguiente manera (usando Express en Node.js):

const express = require('express');
const cors = require('cors');
const app = express();
const corsOptions = {
origin: 'https://frontend.example.com',
methods: ['GET', 'POST'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true,
};
app.use(cors(corsOptions));
app.get('/api/resource', (req, res) => {
res.json({ message: 'Recurso accedido correctamente' });
});
app.listen(3000, () => {
console.log('Servidor escuchando en el puerto 3000');
});

Con esta configuración, el servidor sólo permitirá solicitudes desde https://frontend.example.com con los métodos GET y POST.

Conclusión

CORS es un mecanismo esencial para asegurar nuestras aplicaciones web contra ataques pero debe ser utilizada con precaución. Configurarlo correctamente asegura que tu web esté protegida y pueda compartir recursos de manera segura entre orígenes diferentes.