lunes, 30 de junio de 2025

El esquema de Laravel+Inertia sin Sanctum

 Si tengo una SPA monolítica (con Inertia) con mejoras de Javascript (que realiza llamadas AJAX), ¿necesito el servicio de protección de API de Sanctum?


Es una duda muy común cuando se trabaja con Inertia.js y Laravel.

La respuesta corta es: Probablemente no necesites Sanctum para la protección de tus API si tu SPA monolítica está construida con Inertia.js y el Laravel backend, y las llamadas AJAX son para acciones dentro de tu propia aplicación.

Aquí te explico el porqué y las implicaciones:


Inercia y la Autenticación Basada en Sesiones

Inertia.js está diseñado para funcionar de manera muy fluida con la autenticación basada en sesiones de Laravel, que es la forma tradicional en que Laravel maneja la autenticación para aplicaciones web monolíticas.

Cuando usas Inertia:

  1. Manejo de Sesiones y Cookies: Laravel establece una cookie de sesión (laravel_session) en el navegador del usuario después de que este inicia sesión.

  2. Protección CSRF (Cross-Site Request Forgery): Laravel también utiliza un token CSRF (Cross-Site Request Forgery) que se almacena en una cookie (XSRF-TOKEN) y/o se envía como un campo oculto en formularios o como un encabezado HTTP (X-XSRF-TOKEN). Este token es crucial para proteger tus solicitudes POST, PUT, PATCH y DELETE de ataques CSRF.

  3. Manejo Automático de Solicitudes: Inertia, por debajo, se encarga de que cada solicitud que tu frontend de React/Vue/Svelte hace a Laravel (ya sea una navegación de página o una llamada XHR/AJAX) incluya automáticamente la cookie de sesión y el token CSRF.

Esto significa que, para las llamadas AJAX que haces a tus rutas web de Laravel (las que típicamente definirías en web.php y protegerías con middleware como auth y web), la autenticación y la protección CSRF ya están manejadas por el sistema de sesiones y cookies de Laravel. No necesitas tokens de API como los que proporciona Sanctum para estas interacciones.


¿Cuándo SÍ necesitarías Sanctum?

Sanctum entra en juego principalmente en estos escenarios:

  1. SPA Completamente Desacoplada (Backend-as-an-API): Si tu frontend es una SPA de React/Vue/Angular completamente separada que se comunica con tu backend de Laravel únicamente a través de una API RESTful o GraphQL. En este caso, no hay una sesión web tradicional, y Sanctum (con tokens de API o autenticación SPA) proporciona el mecanismo de autenticación.

  2. Aplicaciones Móviles Nativas: Para aplicaciones iOS o Android que consumen tu API de Laravel.

  3. APIs de Terceros: Cuando necesitas exponer una API para que otras aplicaciones o servicios externos la consuman.

  4. Tokens de Acceso Personal: Para usuarios que quieren generar tokens para acceder a sus propios datos (similar a GitHub o Stripe).


Conclusión para tu Caso

Si tu aplicación es una SPA monolítica con Inertia.js y todas tus llamadas AJAX son realizadas por tu propio frontend de Inertia hacia tu propio backend de Laravel, entonces la respuesta es no, no necesitas Sanctum. El sistema de autenticación basada en sesiones de Laravel, junto con la forma en que Inertia maneja las solicitudes, ya proporciona la seguridad necesaria para esas interacciones.

Usar Sanctum en este escenario no solo sería redundante, sino que podría añadir una capa de complejidad innecesaria a tu autenticación, ya que estarías mezclando dos paradigmas de autenticación diferentes (sesiones vs. tokens de API) sin una necesidad clara. Cíñete a la autenticación de sesión de Laravel, que es lo que Inertia está diseñado para complementar.

domingo, 29 de junio de 2025

La función route en Laravel+Inertia

 De pronto aparece una función route que no está importada y no sé de dónde viene. Quiero saberlo.



¡Ah, la misteriosa función route! Este es un escenario muy común cuando trabajas con Laravel e Inertia.js en el frontend. La función route() que estás viendo en tu código JavaScript (React, Vue, etc.) no es una función global de JavaScript ni una característica nativa del navegador.

Viene de un paquete o configuración que se encarga de exponer tus rutas de Laravel al frontend de JavaScript. Esto es increíblemente útil porque te permite usar los nombres de tus rutas de Laravel directamente en tu código JavaScript, en lugar de tener que codificar URLs manualmente (ej. /dashboard/users/1).


¿De dónde viene route()?

La función route() en el contexto de Laravel + Inertia.js (o cualquier frontend JS que consuma rutas de Laravel) proviene casi con certeza del paquete Ziggy.

¿Qué es Ziggy?

Ziggy es un paquete de Laravel que permite usar tus rutas definidas en Laravel directamente en tu JavaScript. Lo hace generando un archivo JavaScript con todas tus rutas, que luego es cargado en el frontend.

Cómo funciona (en alto nivel):

  1. Configuración en Laravel: Instalás Ziggy en tu proyecto Laravel (composer require tightenco/ziggy).

  2. Generación de Rutas: Configurás Ziggy para que genere un archivo JavaScript (o exponga las rutas globalmente) con todas tus rutas de Laravel. Esto generalmente se hace incluyendo la directiva @routes en tu plantilla Blade principal (ej. app.blade.php).

  3. Disponibilidad en Frontend: Cuando tu aplicación de React (via Inertia) se carga, ese script generado por Ziggy ya se ha cargado en el navegador, haciendo que la función global route() esté disponible para que la uses.


¿Por qué se usa route()?

  • Evitar Hardcoding de URLs: En lugar de escribir Link href="/dashboard/users/1" o axios.get('/api/products'), puedes usar Link href={route('dashboard.users.show', { user: 1 })} o axios.get(route('api.products.index')).

  • Centralización de Rutas: Si cambias la URL de una ruta en tu web.php o api.php de Laravel, solo necesitas cambiarla allí. Ziggy se encargará de actualizar la función route() en el frontend, y no tendrás que buscar y reemplazar manualmente en todo tu código JavaScript.

  • Manejo de Parámetros: La función route() te permite pasar parámetros directamente (ej. route('posts.show', { post: 5 })), y Ziggy se encarga de incrustarlos correctamente en la URL.

  • Consistencia: Mantiene tu frontend y backend sincronizados en cuanto a las URLs.


¿Cómo verificarlo?

  1. Revisa composer.json: Busca tightenco/ziggy en la sección require. Si está ahí, es casi seguro que Ziggy es la fuente.

    JSON
    "require": {
        // ... otras dependencias
        "tightenco/ziggy": "^2.0" // La versión puede variar
    },
    
  2. Revisa resources/views/app.blade.php (o tu plantilla principal): Busca la directiva @routes.

    Blade
    <!DOCTYPE html>
    <html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
        <head>
            {{-- ... --}}
            @routes {{-- <-- Esta es la clave --}}
            @viteReactRefresh
            @vite(['resources/js/app.jsx', 'resources/css/app.css'])
            @inertiaHead
        </head>
        {{-- ... --}}
    </html>
    
  3. Inspecciona el HTML generado en el navegador: Abre las herramientas de desarrollador de tu navegador (F12), ve a la pestaña "Elements" y busca en la sección <head> o al final del <body> un script que contenga la definición de la función route o un script cargado desde /ziggy/routes. A menudo, Ziggy inyecta un script similar a:

    HTML
    <script type="text/javascript">
        const Ziggy = {
            url: "http://localhost",
            port: null,
            defaults: {},
            routes: {
                "dashboard.index": {
                    "uri": "dashboard",
                    "methods": ["GET", "HEAD"]
                },
                // ... más rutas
            }
        };
        // Y luego la función global `route` se define usando Ziggy
        if (typeof window.route === 'undefined') {
            window.route = function (name, parameters, absolute, customUrl) { /* ... */ };
        }
    </script>
    

Si encuentras cualquiera de estas indicaciones, la "misteriosa" función route() viene de Ziggy, y es una característica muy poderosa y útil para integrar tu backend Laravel con tu frontend de React/Inertia.