¿Qué relación hay entre CORS y Access-Control-Allow-Credentials?
La relación entre CORS (Cross-Origin Resource Sharing) y el encabezado Access-Control-Allow-Credentials
es fundamental cuando tu aplicación frontend (por ejemplo, una SPA en frontend.com
) necesita hacer solicitudes a un backend (API en api.com
) y en esas solicitudes deben incluirse credenciales.
Aquí te explico la relación:
CORS (Cross-Origin Resource Sharing)
CORS es un mecanismo de seguridad implementado en los navegadores web que permite a un servidor indicar cualquier origen (dominio, esquema o puerto) diferente al suyo desde el cual un navegador debe permitir la carga de recursos. Es una relajación controlada de la "Same-Origin Policy" (Política del Mismo Origen), que por defecto prohíbe que scripts en una página web accedan a recursos de un origen diferente al de la página.
Cuando un frontend en origin-A.com
intenta hacer una solicitud (ej. fetch
o XMLHttpRequest
) a un recurso en origin-B.com
, el navegador aplica la política del mismo origen. Para permitir esta comunicación "cross-origin", origin-B.com
debe enviar ciertos encabezados CORS en la respuesta que le digan al navegador que está permitido.
Los encabezados CORS clave incluyen:
Access-Control-Allow-Origin
: Indica qué orígenes tienen permiso para acceder al recurso.Access-Control-Allow-Methods
: Indica qué métodos HTTP están permitidos (GET, POST, PUT, DELETE, etc.).Access-Control-Allow-Headers
: Indica qué encabezados de solicitud personalizados están permitidos.Access-Control-Max-Age
: Indica por cuánto tiempo se puede almacenar en caché la respuesta preflight.
Access-Control-Allow-Credentials
Este es un encabezado de respuesta HTTP que el servidor envía para indicar si el navegador debe incluir "credenciales" en una solicitud de origen cruzado.
¿Qué se considera "credenciales" en este contexto?
Las credenciales incluyen:
- Cookies: Las cookies de sesión, cookies de autenticación, etc.
- Encabezados de Autorización: Como los encabezados
Authorization: Bearer <token>
oAuthorization: Basic <base64-encoded-credentials>
. - Certificados de cliente TLS.
La Relación: Un Contrato entre Cliente y Servidor
La relación entre CORS y Access-Control-Allow-Credentials
es un contrato bidireccional entre el navegador (cliente) y el servidor:
-
Petición del Cliente (withCredentials = true):
Para que el navegador siquiera intente enviar credenciales en una solicitud cross-origin, el código JavaScript del cliente (frontend) debe indicarlo explícitamente. Esto se hace configurando la propiedad withCredentials a true en la solicitud:
- Para
fetch()
:fetch(url, { credentials: 'include' })
- Para
XMLHttpRequest
:xhr.withCredentials = true;
Por defecto, los navegadores no envían cookies ni encabezados de autenticación en solicitudes cross-origin para protegerse contra ataques CSRF (Cross-Site Request Forgery) o para evitar la fuga de información sensible.
- Para
-
Respuesta del Servidor (Access-Control-Allow-Credentials: true):
Si el servidor (tu API de Laravel) recibe una solicitud con withCredentials = true y está dispuesto a permitir que esas credenciales se incluyan en la comunicación de origen cruzado, DEBE responder con el encabezado:
Access-Control-Allow-Credentials: true
- Si el servidor responde con
Access-Control-Allow-Credentials: false
(o no lo incluye), y el cliente enviówithCredentials = true
, el navegador ignora la respuesta del servidor y reporta un error de CORS en la consola, bloqueando el acceso del frontend a la respuesta. Esto es una medida de seguridad. - Restricción importante: Si
Access-Control-Allow-Credentials
estrue
, el encabezadoAccess-Control-Allow-Origin
NO PUEDE ser*
(el wildcard). Debe especificar un origen exacto (o la lista de orígenes permitidos). Esto es una medida de seguridad para evitar que cualquier sitio pueda recibir tus credenciales.
- Si el servidor responde con
Escenarios Comunes y su Impacto:
-
API Token Authentication (ej. Laravel Sanctum con tokens para móviles/3rd party):
- Generalmente, no se usa
Access-Control-Allow-Credentials: true
porque los tokens se envían manualmente en el encabezadoAuthorization: Bearer ...
. Si bien el encabezadoAuthorization
se considera una credencial, el cliente no necesita que el navegador maneje automáticamente cookies u otros estados de sesión. Solo necesitaAccess-Control-Allow-Headers
para permitir el encabezadoAuthorization
. - Sin embargo, si tu sistema de tokens se basa en alguna cookie (lo cual no es el estándar para JWT o tokens de portador típicos), entonces
allow-credentials
sí sería relevante.
- Generalmente, no se usa
-
SPA Authentication (ej. Laravel Sanctum con cookies para First-Party Domains):
- Este es el escenario principal para
Access-Control-Allow-Credentials: true
. Si tu SPA está en un subdominio (app.example.com
) y tu API en otro (api.example.com
), y quieres que la SPA se autentique usando las cookies de sesión de Laravel, entonces:- Tu SPA debe hacer solicitudes con
credentials: 'include'
. - Tu API debe responder con
Access-Control-Allow-Origin: https://app.example.com
(no*
) yAccess-Control-Allow-Credentials: true
. - Esto le dice al navegador que está bien enviar y recibir cookies de sesión a través de este origen cruzado específico.
- Tu SPA debe hacer solicitudes con
- Este es el escenario principal para
En resumen:
Access-Control-Allow-Credentials
es un componente específico de CORS que permite la transmisión segura de credenciales (como cookies y encabezados de autenticación) en solicitudes de origen cruzado. Es una "luz verde" explícita del servidor, que debe ser solicitada por el cliente (withCredentials = true
) y confirmada por el servidor, siempre que el Access-Control-Allow-Origin
no sea un wildcard (*
) para mantener la seguridad. Sin esta cabecera, los navegadores se niegan a enviar credenciales en solicitudes de origen cruzado, incluso si el desarrollador del frontend lo solicita.
No hay comentarios:
Publicar un comentario