Mostrando entradas con la etiqueta seguridad. Mostrar todas las entradas
Mostrando entradas con la etiqueta seguridad. Mostrar todas las entradas

martes, 26 de agosto de 2025

Llamados manuales a una API dentro del contexto de una app Inertia

 ¿Los request de las rutas que van en api.php siempre son stateless? ¿Y los request de las rutas que van en web.php siempre son statefull?

¡Es una excelente pregunta! La distinción entre api.php y web.php es fundamental para entender cómo Laravel maneja las solicitudes, especialmente en relación con la autenticación y el estado de la sesión.


Rutas en api.php: Stateless

Sí, las rutas definidas en el archivo routes/api.php son siempre stateless (sin estado) por defecto. Esto significa que Laravel no utiliza cookies ni sesiones para rastrear al usuario a través de múltiples solicitudes.

¿Por qué es esto?

  • Las APIs se diseñan para ser consumidas por aplicaciones cliente que pueden no ser navegadores web (como aplicaciones móviles o scripts del servidor). Estos clientes no siempre manejan cookies de la misma manera que un navegador.

  • En una API sin estado, cada solicitud es un evento independiente. El cliente debe proporcionar alguna forma de autenticación (como un token de API o un token JWT) con cada solicitud, y el servidor verifica la validez de ese token en cada petición. Esto es ideal para arquitecturas SPA (Single Page Application) y microservicios, ya que permite que la aplicación cliente esté desacoplada de la sesión de Laravel.

Laravel aplica un middleware especial a estas rutas (api en el archivo app/Http/Kernel.php), que incluye una capa de "limitación de velocidad" y la configuración para el manejo de tokens.


Rutas en web.php: Statefull

Las rutas en routes/web.php son siempre statefull (con estado) por defecto. Esto significa que Laravel utiliza cookies y sesiones para mantener un seguimiento del usuario a lo largo del tiempo.

¿Por qué es esto?

  • Las aplicaciones web tradicionales, diseñadas para ser renderizadas por el servidor, se basan en la sesión para funcionar. Cuando un usuario inicia sesión, el servidor guarda su información en la sesión y le envía al navegador una cookie de sesión.

  • En las siguientes solicitudes, el navegador envía automáticamente esta cookie, y Laravel puede usarla para identificar al usuario y mantener su estado de sesión (por ejemplo, saber si está autenticado, su carrito de compras, etc.).

  • El grupo de middleware que Laravel aplica a las rutas web incluye \Illuminate\Session\Middleware\StartSession y \App\Http\Middleware\VerifyCsrfToken, que son esenciales para el manejo del estado de la sesión y la seguridad.

En resumen, la distinción principal no es que un tipo de solicitud sea fundamentalmente diferente, sino que Laravel les aplica diferentes middlewares para que se comporten de manera que tenga sentido para sus respectivos casos de uso: API sin estado y Web con estado.


Un request de api puede ser tratado como statefull por medio de sanctum?

Sí, ¡esa es la magia de Sanctum!

El propósito principal de Sanctum es cerrar la brecha entre las APIs sin estado y la necesidad de tener una autenticación con estado en una aplicación de una sola página (SPA) que se ejecuta en el navegador.


¿Cómo funciona?

Sanctum te permite usar la misma autenticación basada en cookies que las rutas de web.php para tus rutas en api.php. Esto es lo que sucede detrás de bambalinas:

  1. Negociación de Origen Cruzado: Cuando tu SPA (spa.test) hace una solicitud a tu backend (api.test), el navegador inicia un "handshake" (saludo) de CORS. El navegador envía la cookie de sesión de tu dominio de la API.

  2. Verificación de la cookie: Sanctum intercepta la solicitud. En lugar de buscar un token de API en la cabecera Authorization, busca la cookie de sesión de Laravel.

  3. Aprobación: Si el usuario está autenticado en esa sesión (es decir, la cookie es válida), Sanctum valida la petición y la permite continuar como si fuera una solicitud con estado.

Esencialmente, Sanctum es un guardián de autenticación para las rutas API que te permite usar tanto tokens de portador (bearer tokens) para clientes móviles como cookies para tu SPA.

¿Cuándo usarlo?

  • SPA: Cuando estás construyendo una aplicación de una sola página (SPA) con un framework como Vue, React o Angular. Las cookies son la forma más sencilla de manejar la autenticación en este escenario.

  • API y Web: Cuando necesitas una API que pueda ser consumida tanto por tu aplicación web (que usa cookies) como por otras aplicaciones (que usarán tokens de portador).

Sanctum hace que un "request de api" se comporte de una manera híbrida. Por un lado, sigue siendo una API sin estado en el sentido de que no depende de la sesión de Laravel. Pero por otro, usa la identidad de la sesión para autenticar al usuario, lo que lo hace parecer con estado.


Va bien todo esto con Inertia?

Absolutamente, ¡Sanctum y Inertia van de la mano a la perfección!


¿Por qué Inertia y Sanctum funcionan tan bien juntos?

Inertia.js está diseñado para funcionar como una aplicación de una sola página (SPA) sin el "dolor de cabeza" de una API. Esto significa que usa las rutas de web.php de Laravel y el sistema de sesión/cookies que ya conoces, lo que evita la necesidad de tokens de portador o la complejidad de CORS.

Sin embargo, en el fondo, Inertia sigue siendo una SPA que se comunica con tu servidor a través de peticiones XHR/AJAX. Aquí es donde Sanctum se vuelve útil, aunque de una manera un poco diferente a la que describimos anteriormente.

  1. Manejo del CSRF: Inertia, por defecto, se encarga de enviar el token CSRF (no el XSRF) de la cookie de Laravel con cada petición POST, PUT o DELETE. Para las peticiones de Inertia, el token CSRF es lo que valida el formulario y asegura que la solicitud provenga de la aplicación.

  2. Autenticación sin problemas: Cuando un usuario inicia sesión en tu aplicación Inertia, el servidor de Laravel crea una cookie de sesión (laravel_session). Cada petición subsiguiente de Inertia al servidor (a través de Inertia.js) incluye automáticamente esta cookie de sesión. El servidor de Laravel reconoce la cookie, sabe que el usuario está autenticado y maneja la petición sin ningún problema.


Conclusión

La combinación de Inertia y Sanctum es tan efectiva que a menudo se le conoce como el "modelo SPA-amistoso" de Laravel. Sanctum proporciona el middleware necesario para las rutas api.php, permitiendo que Inertia se comunique con el servidor de manera segura y sin complicaciones.

No necesitas hacer nada especial. Simplemente configura Inertia.js para que utilice tus rutas de web.php, y Sanctum se encargará del resto, asegurando que tus peticiones con AJAX sean seguras, ¡como si fueran una solicitud de formulario normal!


Quiero hacer yo las peticiones Ajax de manera explícita con fetch. ¿Las rutas las creo en web.php o en api.php?

Las rutas para tus peticiones fetch deben ir en api.php.


¿Por qué api.php?

Aunque técnicamente podrías usar web.php, usar api.php es la práctica recomendada y la más segura por las siguientes razones:

  1. Protección CSRF: Las rutas en web.php requieren un token CSRF (Cross-Site Request Forgery) para las solicitudes POST, PUT y DELETE. Este token se incluye automáticamente si usas formularios o librerías como Inertia, pero si haces peticiones fetch manuales, tendrás que asegurarte de obtener el token de la cookie y enviarlo en la cabecera X-XSRF-TOKEN con cada solicitud. Es un paso extra que puede complicar tu código.

  2. Middlewares de API: Laravel ya tiene una pila de middlewares optimizada para APIs en el archivo api.php. Estos middlewares gestionan la autenticación sin estado (con tokens de portador) y la limitación de peticiones (rate limiting), que son ideales para peticiones AJAX.

  3. Coherencia y organización: Poner tus rutas AJAX en api.php mantiene tu código organizado. Las rutas de web.php se usan para las páginas de tu aplicación (vistas de blade o componentes de Inertia), mientras que las rutas de api.php se usan para los endpoints que devuelven datos (JSON) para tu frontend.

Ejemplo de cómo hacerlo

Aquí tienes un ejemplo de cómo crear una ruta en api.php y cómo hacer la petición fetch desde tu JavaScript.

1. Define la ruta en routes/api.php:

PHP
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

// Agregamos el middleware 'auth:sanctum' para proteger la ruta
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
    return $request->user();
});

2. Haz la petición fetch desde tu JavaScript:

Para que fetch funcione con Sanctum, necesitas la configuración adecuada. Aquí está un ejemplo completo de cómo configurar y usar fetch:

Ejemplo de Fetch con Sanctum
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sanctum Fetch Example</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
body {
font-family: 'Inter', sans-serif;
}
</style>
</head>
<body class="bg-gray-100 flex items-center justify-center min-h-screen">

<div class="bg-white p-8 rounded-lg shadow-md w-full max-w-md">
<h1 class="text-2xl font-bold mb-6 text-center text-gray-800">Sanctum Fetch Example</h1>
<div class="space-y-4">
<button id="loginBtn" class="w-full bg-blue-500 text-white font-semibold py-2 px-4 rounded-lg shadow-md hover:bg-blue-600 transition-colors">
Iniciar Sesión
</button>
<button id="fetchUserBtn" class="w-full bg-green-500 text-white font-semibold py-2 px-4 rounded-lg shadow-md hover:bg-green-600 transition-colors">
Obtener Usuario (API Protegida)
</button>
</div>

<div id="messageBox" class="mt-6 p-4 rounded-lg hidden"></div>
</div>

<script>
// URL de la API de Laravel
const API_URL = 'http://localhost:8000';

// Referencias a los elementos del DOM
const loginBtn = document.getElementById('loginBtn');
const fetchUserBtn = document.getElementById('fetchUserBtn');
const messageBox = document.getElementById('messageBox');

// Función para mostrar un mensaje al usuario
function showMessage(message, type = 'info') {
messageBox.textContent = message;
messageBox.classList.remove('hidden', 'bg-red-200', 'bg-green-200', 'bg-blue-200', 'text-red-800', 'text-green-800', 'text-blue-800');
if (type === 'error') {
messageBox.classList.add('bg-red-200', 'text-red-800');
} else if (type === 'success') {
messageBox.classList.add('bg-green-200', 'text-green-800');
} else {
messageBox.classList.add('bg-blue-200', 'text-blue-800');
}
}

// Manejador del clic para el botón de inicio de sesión
loginBtn.addEventListener('click', async () => {
try {
// Petición a la ruta que genera el token CSRF y la cookie de sesión
showMessage('Iniciando sesión...');
const response = await fetch(`${API_URL}/sanctum/csrf-cookie`);

if (response.ok) {
// Si la petición fue exitosa, el navegador ya tiene la cookie CSRF.
// Ahora, la siguiente petición se enviará con la cookie de sesión.
showMessage('¡Sesión iniciada con éxito! Ahora puedes obtener los datos del usuario.', 'success');
} else {
showMessage(`Error al iniciar sesión: ${response.status}`, 'error');
}
} catch (error) {
console.error('Login error:', error);
showMessage('Error al iniciar sesión. Verifica que el servidor de Laravel esté activo.', 'error');
}
});

// Manejador del clic para el botón de obtener usuario
fetchUserBtn.addEventListener('click', async () => {
try {
showMessage('Obteniendo datos del usuario...');
// Petición a la ruta protegida. El navegador enviará automáticamente
// la cookie de sesión que Sanctum necesita.
const response = await fetch(`${API_URL}/api/user`);
const data = await response.json();

if (response.ok) {
// Si la petición es exitosa, muestra los datos del usuario.
showMessage(`Usuario: ${JSON.stringify(data)}`, 'success');
} else if (response.status === 401) {
// Si la petición falla con un 401, el usuario no está autenticado
showMessage('No autenticado. Por favor, inicia sesión primero.', 'error');
} else {
showMessage(`Error: ${response.status}`, 'error');
}
} catch (error) {
console.error('Fetch user error:', error);
showMessage('Error al obtener datos. Verifica la conexión.', 'error');
}
});
</script>

</body>
</html>

El ejemplo anterior te muestra cómo:

  1. Hacer la primera petición a sanctum/csrf-cookie para obtener la cookie de sesión de Laravel.

  2. Hacer una segunda petición a una ruta de la API protegida con el middleware auth:sanctum.

El navegador se encarga automáticamente de enviar la cookie en las siguientes peticiones a tu dominio, y Sanctum se encarga de autenticar al usuario usando esa cookie.


Necesito una app con Inertia que además consuma una API, y que esta API se base los mismos mecanismos de seguridad que la aplicación Inertia.

¡Excelente pregunta! Esta es una de las mayores fortalezas de Laravel Sanctum. No solo te protege con las cookies de sesión para tu aplicación Inertia, sino que también te permite usar el mismo sistema de autenticación para tus propias peticiones fetch a la API.

No necesitas tokens de portador ni ninguna otra configuración compleja. Sanctum se encarga de todo esto por ti.

Aquí tienes un ejemplo completo que simula una aplicación de una sola página (SPA) que se autentica a través de Sanctum. Este código te mostrará cómo las peticiones a la API y las peticiones a tus rutas web utilizan el mismo mecanismo de seguridad, todo gracias a la cookie de sesión de Laravel.

App con Inertia y API usando Sanctum
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Inertia + Sanctum + API App</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
body {
font-family: 'Inter', sans-serif;
transition: all 0.3s ease-in-out;
}
.container-card {
background-image: linear-gradient(135deg, #f0f4f8 0%, #d9e2ec 100%);
}
.btn-primary {
background-image: linear-gradient(to right, #4f46e5, #6366f1);
transition: all 0.3s ease;
}
.btn-primary:hover {
box-shadow: 0 4px 15px rgba(79, 70, 229, 0.4);
transform: translateY(-2px);
}
.btn-secondary {
background-color: #f3f4f6;
color: #4b5563;
transition: all 0.3s ease;
}
.btn-secondary:hover {
background-color: #e5e7eb;
transform: translateY(-2px);
}
</style>
</head>
<body class="bg-gray-100 flex items-center justify-center min-h-screen p-4">

<div class="container-card w-full max-w-lg p-8 rounded-2xl shadow-xl border border-gray-200">
<h1 class="text-3xl font-extrabold text-gray-900 mb-2 text-center">Inertia & API App</h1>
<p class="text-gray-600 mb-8 text-center">
Demostración de cómo Sanctum gestiona la seguridad para ambos tipos de peticiones.
</p>

<div id="authStatus" class="mb-6 p-3 rounded-lg text-center font-medium bg-red-100 text-red-700 hidden">
No autenticado. Por favor, inicia sesión.
</div>

<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<button id="loginBtn" class="w-full py-3 px-6 rounded-lg text-white font-bold btn-primary">
Iniciar Sesión (SPA)
</button>
<button id="logoutBtn" class="w-full py-3 px-6 rounded-lg font-bold btn-secondary hidden">
Cerrar Sesión
</button>
<button id="getInertiaDataBtn" class="w-full py-3 px-6 rounded-lg text-white font-bold btn-primary">
Obtener Datos (Web)
</button>
<button id="getApiDataBtn" class="w-full py-3 px-6 rounded-lg text-white font-bold btn-primary">
Obtener Datos (API)
</button>
</div>

<div id="resultsBox" class="mt-8 p-6 bg-white border border-gray-300 rounded-lg shadow-inner min-h-[100px] whitespace-pre-wrap overflow-x-auto text-sm text-gray-800">
<!-- Los resultados se mostrarán aquí -->
</div>
</div>

<script>
// URL base de tu aplicación Laravel. ¡Asegúrate de cambiarla!
const BASE_URL = 'http://localhost:8000';

// Referencias a los elementos del DOM
const authStatus = document.getElementById('authStatus');
const loginBtn = document.getElementById('loginBtn');
const logoutBtn = document.getElementById('logoutBtn');
const getInertiaDataBtn = document.getElementById('getInertiaDataBtn');
const getApiDataBtn = document.getElementById('getApiDataBtn');
const resultsBox = document.getElementById('resultsBox');

// Función para mostrar mensajes de estado
function showStatus(isLoggedIn) {
if (isLoggedIn) {
authStatus.classList.add('hidden');
loginBtn.classList.add('hidden');
logoutBtn.classList.remove('hidden');
} else {
authStatus.classList.remove('hidden');
loginBtn.classList.remove('hidden');
logoutBtn.classList.add('hidden');
}
}

// Función para mostrar los resultados
function showResults(data, endpoint) {
const title = endpoint === 'web' ? 'Datos desde la Ruta Web' : 'Datos desde la Ruta API';
const formattedData = JSON.stringify(data, null, 2);
resultsBox.innerHTML = `
<div class="font-bold mb-2">${title}</div>
<pre class="bg-gray-100 p-4 rounded-md overflow-x-auto">${formattedData}</pre>
`;
}

// --- Lógica de Autenticación y Peticiones ---

// 1. Iniciar Sesión: El paso más importante para las SPAs.
// Llama a esta ruta para que Laravel establezca una cookie de sesión.
loginBtn.addEventListener('click', async () => {
try {
resultsBox.textContent = 'Intentando iniciar sesión...';
// Petición a la ruta de Sanctum para obtener la cookie de sesión.
const response = await fetch(`${BASE_URL}/sanctum/csrf-cookie`);

if (response.ok) {
// Una vez que la cookie está en el navegador, todas las peticiones futuras
// a este dominio la incluirán automáticamente.
resultsBox.textContent = '¡Sesión iniciada con éxito! La cookie de sesión ya está activa.';
showStatus(true);
} else {
resultsBox.textContent = `Error: ${response.status} - ${response.statusText}`;
}
} catch (error) {
console.error('Login error:', error);
resultsBox.textContent = 'Error al conectar con el servidor. Verifica que esté funcionando.';
}
});

// 2. Obtener datos de una Ruta Web (Simulando Inertia)
// El navegador enviará la cookie de sesión automáticamente.
// Esta ruta debe estar protegida por el middleware 'auth'.
getInertiaDataBtn.addEventListener('click', async () => {
try {
resultsBox.textContent = 'Obteniendo datos de la ruta web (simulando Inertia)...';
const response = await fetch(`${BASE_URL}/dashboard`);
const data = await response.json(); // Asumimos que la ruta devuelve JSON para este ejemplo

if (response.ok) {
// Si la respuesta es 200, el usuario estaba autenticado
showResults(data, 'web');
} else if (response.status === 401) {
// Si la respuesta es 401, la cookie no era válida o no existe
resultsBox.textContent = 'No autenticado. Por favor, inicia sesión.';
showStatus(false);
} else {
resultsBox.textContent = `Error: ${response.status} - ${response.statusText}`;
}
} catch (error) {
console.error('Fetch web error:', error);
resultsBox.textContent = 'Error al obtener datos web.';
}
});

// 3. Obtener datos de una Ruta API (usando `fetch`)
// El navegador enviará la misma cookie de sesión, sin necesidad de tokens.
// Esta ruta debe estar protegida por el middleware 'auth:sanctum'.
getApiDataBtn.addEventListener('click', async () => {
try {
resultsBox.textContent = 'Obteniendo datos de la API...';
const response = await fetch(`${BASE_URL}/api/user`);
const data = await response.json();

if (response.ok) {
// Sanctum reconoció la cookie y autenticó la petición
showResults(data, 'api');
} else if (response.status === 401) {
// Falló la autenticación
resultsBox.textContent = 'No autenticado. Por favor, inicia sesión.';
showStatus(false);
} else {
resultsBox.textContent = `Error: ${response.status} - ${response.statusText}`;
}
} catch (error) {
console.error('Fetch API error:', error);
resultsBox.textContent = 'Error al obtener datos de la API.';
}
});

// 4. Cerrar sesión
// Esto borra la cookie de sesión del servidor
logoutBtn.addEventListener('click', async () => {
try {
resultsBox.textContent = 'Cerrando sesión...';
// Puedes crear una ruta de API para cerrar la sesión
const response = await fetch(`${BASE_URL}/logout`, { method: 'POST' }); // Simulamos una petición POST a la ruta de logout

if (response.ok) {
resultsBox.textContent = 'Sesión cerrada con éxito.';
showStatus(false);
} else {
resultsBox.textContent = `Error: ${response.status} - ${response.statusText}`;
}
} catch (error) {
console.error('Logout error:', error);
resultsBox.textContent = 'Error al cerrar sesión.';
}
});

// Verificación inicial del estado
showStatus(false);
</script>

</body>
</html>

Cómo funciona

  1. Inicio de Sesión (SPA Authentication): Al hacer clic en "Iniciar Sesión", la aplicación hace una petición a la ruta sanctum/csrf-cookie. Esto hace que Laravel cree una cookie de sesión con el token CSRF y la envíe al navegador.

  2. Peticiones Automáticas: Una vez que el navegador tiene la cookie de sesión, la adjuntará automáticamente a todas las peticiones posteriores a ese dominio (tanto a tus rutas web como a tus rutas de api.php).

  3. Sanctum en Acción: Sanctum, usando su middleware auth:sanctum, intercepta estas peticiones. Si detecta la cookie de sesión, autentica al usuario sin necesidad de un token de portador. Esto hace que tu API sea segura de forma nativa para tu frontend SPA.

Este enfoque te permite mantener toda tu lógica de seguridad centralizada y te evita tener que gestionar tokens de forma manual en tu frontend. ¡Es una solución limpia y robusta para tu proyecto!


¿La URL /sanctum/csrf-cookie es un endpoint, una ruta, u otra cosa? ¿No es inseguro que devuelva una cookie de sesión sin pedir credenciales a cambio?

Tu pregunta es excelente y toca un punto clave de la seguridad. Es muy perspicaz.

La URL /sanctum/csrf-cookie es una ruta (un endpoint). Su propósito principal no es autenticarte, sino iniciar el "protocolo" de comunicación entre tu SPA y Laravel.


¿Por qué no es inseguro?

El hecho de que esta ruta devuelva una cookie sin pedir credenciales no la hace insegura, porque la cookie en sí misma no concede acceso a los datos de tu usuario. Piensa en ella como una llave de entrada que te permite pasar por la primera puerta, pero no te abre las puertas de la casa.

Aquí está el desglose:

  • Petición 1: /sanctum/csrf-cookie

    • Lo que hace: Esta petición inicial le dice a Laravel: "Hola, soy una SPA y necesito comunicarme contigo".

    • Lo que devuelve: Laravel responde con una cookie de sesión (que contiene un token CSRF). Esta cookie es simplemente un identificador de sesión. No sabe quién eres, solo que eres un "visitante" en ese momento. Esta cookie es el pegamento que unirá tus futuras peticiones con la sesión de Laravel.

    • Seguridad: No se pide autenticación porque no se está accediendo a datos protegidos. Esta ruta es pública y solo sirve para establecer el estado de la sesión.

  • Petición 2: /api/user (u otra ruta protegida)

    • Lo que hace: Tu navegador envía esta petición a la API, adjuntando automáticamente la cookie de sesión que recibió antes.

    • Lo que comprueba Laravel: Ahora sí, el middleware de autenticación de Laravel (auth:sanctum) entra en juego. Comprueba si la cookie de sesión está asociada a un usuario autenticado.

    • Autenticación: Si el usuario ha iniciado sesión previamente (por ejemplo, a través de una página de login), Laravel encontrará el usuario en la sesión y permitirá el acceso. Si el usuario no ha iniciado sesión, la petición fallará con un error 401 Unauthorized (no autorizado), sin importar que tengas la cookie de sesión.


La distinción clave: ¿Quién eres vs. qué puedes hacer?

La cookie de sesión de /sanctum/csrf-cookie solo identifica la sesión de un visitante, no la identidad de un usuario. Es el proceso de autenticación posterior (por ejemplo, enviando las credenciales de inicio de sesión a otra ruta) lo que vincula la sesión con un usuario específico. Una vez que esa vinculación ocurre, la misma cookie se usa para proteger todas las peticiones futuras, tanto en la web como en la API, asegurando que solo el usuario correcto pueda acceder a sus datos.

Es una estrategia segura y eficiente que evita la complejidad de gestionar tokens de portador en el lado del cliente.


Mi app usa el login del starterkit de Inertia/React, con cierta modificación que incorporé, pero que en definitiva termina llamando a Auth::login($user, $this->boolean('remember'));. Creo que en mi caso no tengo que llamar a /sanctum/csrf-cookie ni antes ni después de hacer el login. ¿Estoy acertado?

Sí, estás completamente en lo cierto. No necesitas llamar a /sanctum/csrf-cookie ni antes ni después de tu proceso de inicio de sesión con el starter kit de Inertia.js.


¿Por qué Inertia lo hace por ti?

El starter kit de Inertia está diseñado para que te olvides de esta complejidad. Cuando el navegador realiza una solicitud GET a la ruta de login para mostrar la vista, el servidor de Laravel automáticamente establece la cookie de sesión.

La magia ocurre cuando envías el formulario de login. Inertia.js sabe que está haciendo una solicitud POST y, gracias a su configuración por defecto, automáticamente toma el token CSRF de la cookie de sesión y lo incluye en la cabecera de la petición X-XSRF-TOKEN.

Por lo tanto, la secuencia es la siguiente:

  1. El navegador carga la página de inicio de sesión de Inertia.

  2. Laravel envía al navegador una respuesta HTML que incluye la cookie de sesión con el token CSRF.

  3. El usuario introduce sus credenciales y hace clic en "Login".

  4. Inertia intercepta la petición, añade el token CSRF a la cabecera de la solicitud y la envía a Laravel.

  5. Laravel, a través de sus middlewares, valida el token CSRF y autentica al usuario.

  6. La llamada a Auth::login() asocia el usuario a la sesión actual, y la cookie de sesión permanece activa para las siguientes peticiones.

En esencia, Inertia/React y el starter kit de Laravel ya han implementado la lógica para el "handshake" de Sanctum por ti. No tienes que preocuparte por hacerlo de manera manual.


¿Alcanza el nivel de seguridad sin la protección del middleware auth:sanctum en las rutas de api.php?

No, no es seguro. Si tus rutas de api.php no tienen el middleware auth:sanctum (o cualquier otro middleware de autenticación), están completamente desprotegidas. Cualquiera podría acceder a ellas, incluso si el usuario no ha iniciado sesión.


¿Cómo funciona la seguridad en tu caso?

El starter kit de Inertia.js está diseñado para funcionar en conjunto con las rutas protegidas de Laravel.

  1. Protección de rutas web: El middleware web que se aplica a las rutas de web.php ya contiene auth, StartSession y VerifyCsrfToken. Esto protege automáticamente las páginas de tu aplicación.

  2. Protección de rutas de API: El middleware auth:sanctum de las rutas de api.php es el que realmente verifica la autenticidad de las peticiones. Cuando tu aplicación de Inertia hace una llamada a un endpoint de la API, el navegador envía la cookie de sesión. El middleware auth:sanctum de Laravel es el responsable de interceptar esa cookie, verificar si pertenece a un usuario autenticado y permitir el acceso. Sin este middleware, la API simplemente serviría los datos a quien los pida.

En resumen, el hecho de que uses el login de Inertia no significa que tus rutas de API sean seguras por arte de magia. Tienes que aplicar el middleware auth:sanctum para que las peticiones a la API sean seguras.

No te preocupes, el auth:sanctum es lo que te permite usar las cookies de sesión para proteger tu API de la misma forma que tu aplicación web. Sin él, tu API estaría abierta al público.