¿Qué protección contra CSRF (Cross-Site Request Forgery) ocurre cuando se usa Sanctum para autenticar una SPA (single-page application)?
En el contexto de la autenticación de SPAs con Laravel Sanctum (cuando el frontend y el backend comparten un "first-party domain"), la protección CSRF (Cross-Site Request Forgery) es un elemento de seguridad crucial que se implementa de una manera ligeramente adaptada a las necesidades de las aplicaciones de una sola página.
Primero, recordemos qué es CSRF:
Un ataque CSRF ocurre cuando un sitio web malicioso engaña al navegador de un usuario ya autenticado para que realice una solicitud no deseada (ej. cambiar la contraseña, hacer una compra) en un sitio legítimo donde el usuario tiene una sesión activa. El navegador envía automáticamente las cookies de sesión con la solicitud, lo que hace que parezca una solicitud legítima del usuario.
¿Cómo funciona la Protección CSRF en Laravel Sanctum (para SPAs)?
Laravel Sanctum extiende el mecanismo de protección CSRF tradicional de Laravel para que funcione sin problemas con las SPAs. Esto se logra mediante un intercambio de tokens que involucra una cookie y un encabezado HTTP:
-
Paso Inicial: Obtener el
XSRF-TOKEN
(Solicitud a/sanctum/csrf-cookie
)- Tu aplicación frontend (SPA) debe, en algún momento (generalmente al cargar la aplicación o antes de cualquier solicitud de autenticación), hacer una solicitud GET al endpoint
/sanctum/csrf-cookie
. - Cuando Laravel recibe esta solicitud, hace dos cosas:
- Establece una cookie llamada
XSRF-TOKEN
: Esta cookie contiene el token CSRF generado por Laravel y se envía de vuelta al navegador. Esta cookie NO esHttpOnly
, lo que significa que el JavaScript de tu frontend puede leer su valor. - Establece la cookie de sesión de Laravel: Si aún no hay una sesión activa, se inicia una y se envía la cookie de sesión (
laravel_session
).
- Establece una cookie llamada
- Importante: Debido a la
, una página maliciosa en un dominio diferente no puede leer esta cookiePolítica del Mismo Origen XSRF-TOKEN
.
- Tu aplicación frontend (SPA) debe, en algún momento (generalmente al cargar la aplicación o antes de cualquier solicitud de autenticación), hacer una solicitud GET al endpoint
-
Paso en el Frontend: Leer la cookie y enviar el encabezado
X-XSRF-TOKEN
- Una vez que tu SPA ha recibido la cookie
XSRF-TOKEN
, para todas las solicitudes POST, PUT, PATCH o DELETE subsiguientes (es decir, cualquier solicitud que no sea GET, HEAD o OPTIONS), tu código JavaScript frontend debe:- Leer el valor de la cookie
XSRF-TOKEN
. - Enviar ese valor en un encabezado HTTP personalizado llamado
X-XSRF-TOKEN
(oX-CSRF-TOKEN
si estás usando el nombre de encabezado tradicional de Laravel, aunque Sanctum prefiereX-XSRF-TOKEN
).
- Leer el valor de la cookie
- Las librerías HTTP populares como Axios y Fetch (cuando se configura adecuadamente) a menudo se pueden configurar para hacer esto automáticamente.
- Una vez que tu SPA ha recibido la cookie
-
Paso en el Backend: Verificación del
VerifyCsrfToken
Middleware- Cuando una solicitud llega a tu API de Laravel (a una ruta protegida por el middleware
web
oapi
donde el middleware\App\Http\Middleware\VerifyCsrfToken::class
está activo), este middleware realiza la verificación:- Compara el valor del encabezado
X-XSRF-TOKEN
(que envió tu frontend) con el valor de la cookieXSRF-TOKEN
(que el navegador envió automáticamente). - Si los dos valores no coinciden, o si el encabezado
X-XSRF-TOKEN
está ausente en una solicitud que lo requiere, Laravel considera que es un posible ataque CSRF y rechaza la solicitud, devolviendo un error HTTP 419 (Page Expired) o 403 (Forbidden).
- Compara el valor del encabezado
- Cuando una solicitud llega a tu API de Laravel (a una ruta protegida por el middleware
¿Por qué esta protección funciona contra los ataques CSRF?
- Imposibilidad de leer la cookie (
XSRF-TOKEN
) desde otro origen: Debido a la Política del Mismo Origen, un sitio web malicioso enmalicious.com
no puede acceder directamente a las cookies establecidas por tu dominio (tuapp.com
). Por lo tanto, no puede leer el valor delXSRF-TOKEN
de la cookie. - Dificultad de establecer encabezados personalizados en requests cross-origin: Un sitio malicioso puede hacer que el navegador del usuario envíe una solicitud POST cross-origin. Sin embargo, no puede añadir encabezados HTTP arbitrarios como
X-XSRF-TOKEN
sin que el navegador primero haga una solicitud "preflight" (OPTIONS) y obtenga permiso explícito del servidor a través de los encabezados CORS. Si el servidor no permite elX-XSRF-TOKEN
para ese origen malicioso, la solicitud preflight fallará y la solicitud real nunca se enviará.
De esta manera, solo tu propia SPA, que está en un dominio de primera parte (o configurado como tal en SANCTUM_STATEFUL_DOMAINS
) y que puede leer la cookie XSRF-TOKEN
y enviar el encabezado X-XSRF-TOKEN
correctamente, podrá hacer solicitudes exitosas a tu API. Cualquier solicitud proveniente de un sitio malicioso fallará la comprobación del token CSRF.
No hay comentarios:
Publicar un comentario