“React frontend on Laravel” almost always raises the authentication question: do we run a separate SPA with Sanctum tokens, or keep everything in one app with Inertia.js and plain Laravel sessions?
Both are production-grade; they solve different shapes of the same problem. Here is how to choose without regretting it in month six.
- Architecture context: Inertia.js with Laravel and React — SPA without a separate API.
Two models, one diagram
Inertia.js session auth. The React pages live in the Laravel app. Login is a normal POST to a Laravel route; the browser gets the session cookie; every subsequent Inertia request carries it automatically. Middleware, policies and auth()->user() work exactly as in Blade. There is no token anywhere.
Sanctum SPA. The React app is deployed separately (its own domain or subdomain). Sanctum's stateful mode authenticates it with cookies via /sanctum/csrf-cookie and the session guard — or, for non-browser clients, personal access tokens in the Authorization: Bearer header.
| Aspect | Inertia session auth | Sanctum SPA (tokens) |
|---|---|---|
| Where the frontend lives | Same app, same repo | Separate app and deploy |
| Credentials | Session cookie (HttpOnly) | Token in header (or cookie, stateful mode) |
| CSRF | Automatic, same-origin | Must be wired (/sanctum/csrf-cookie) |
| Logout / revocation | Session invalidated server-side | Delete token (per device) |
| Multi-device sessions | Session per browser | One token per device — a feature for mobile |
| XSS exposure | Cookie not readable by JS | Token readable if stored in localStorage |
| Setup cost | Zero extra | CORS, token lifecycle, refresh handling |
What Sanctum's token model buys — and costs
Tokens are the right answer when a non-browser client consumes the backend: mobile apps, desktop tools, integrations. Each device holds its own token, revocation is per-device, and the API can be opened to partners later. The costs are real too: you now maintain a public contract — versioning, response shapes, error formats — plus CORS and token storage decisions on the client.
Warning: Never store tokens in
localStorageif you can avoid it. One XSS and the token is stolen. For first-party SPAs, use Sanctum's stateful cookie mode; for mobile, use the platform's secure storage.
What Inertia's session model buys
Zero authentication plumbing. Login, password reset, email verification, 2FA — every Laravel auth recipe applies unchanged, because it is a normal Laravel app. The frontend never sees a credential. Combined with CSRF tokens included in Inertia requests automatically, the attack surface is the classic, well-understood Laravel surface — not a new one you designed last week.
- The honest limitation: session auth serves exactly one client — the web app. A mobile app cannot reuse it.
The decision rule we use
- Web app only, now and for the foreseeable roadmap → Inertia + sessions. You ship faster and maintain less.
- Mobile app or public API on the roadmap within months → start with Inertia anyway, structure controllers so an API layer can be extracted (resources, form requests, policies — all reusable), and add Sanctum when the second client actually appears.
- Separate frontend team with its own release cycle → Sanctum SPA with a versioned API. The organizational boundary justifies the technical one.
A premature API is the most expensive way to authenticate users who never asked for it — the same reasoning as in Inertia.js vs Livewire, applied to auth.
The migration path (Inertia → +Sanctum)
When the second client arrives, nothing is thrown away: controllers already return resources, validation lives in FormRequests, authorization in policies. You add API routes that call the same logic, install Sanctum, issue tokens — and the Inertia app keeps running on sessions in parallel. We have done this extraction on production products; it is days of work, not a rewrite.
Planning an app where this decision is on the horizon?
See Laravel development services — we design the seams up front.
FAQ
Is Inertia.js session auth secure without tokens?
Yes — it is Laravel's classic session model: HttpOnly cookies, CSRF protection, server-side revocation. For web-only apps it is the safer default than tokens in JS storage.
When do I actually need Sanctum?
When a client lives outside the Laravel app: mobile, desktop, a separately deployed frontend, or a public partner API.
Can I start with Inertia and add an API later?
Yes — extract API endpoints behind Sanctum when the second client appears; controllers, policies and validation are reused.
👉 Designing auth for a new product? Check our Laravel development services or hire a Laravel developer — we pick the model per roadmap, not per habit.
📖 Read more: Inertia.js with Laravel and React, Inertia.js vs Livewire and the OneCRMApp architecture case study.