I have a Vue SPA on app.example.com and a Laravel 12 API on api.example.com, plus a mobile app. The Sanctum docs mention both cookies and tokens and I am confused which one to use for what, and why I get 401 or 419 on the SPA.
DEV3 Developer Forum
Sanctum: when do I use SPA cookie auth and when API tokens?
Every post is reviewed first. Usually reviewed within 24 hours.
1 reply
Sanctum offers two separate mechanisms. Pick by client type.
1. SPA cookie (session) authentication
For a first-party SPA on the same top-level domain (app.example.com and api.example.com are fine, example.com vs other.com is not). No tokens are stored in JavaScript, so XSS cannot steal them.
Setup checklist:
.env:SESSION_DOMAIN=.example.comandSANCTUM_STATEFUL_DOMAINS=app.example.com(include the port in local dev, e.g.localhost:5173).- CORS
supports_credentialsmust betrue(publish withphp artisan config:publish corsin Laravel 12). - The client sends credentials:
axios.defaults.withCredentials = true. - Before login call
GET /sanctum/csrf-cookie, thenPOST /login. Axios then sends theX-XSRF-TOKENheader automatically. - Routes use
auth:sanctum.
Typical errors: 419 means the CSRF cookie was not fetched or the header is missing; 401 means the origin is not in the stateful list or the session cookie is not sent (domain, SameSite or credentials flag).
2. API tokens
For mobile apps, third-party clients and scripts.
$token = $user->createToken('ios', ['orders:read'])->plainTextToken;
The client sends Authorization: Bearer <token>. Check abilities with $request->user()->tokenCan('orders:read'). Tokens are hashed in the DB, shown once, and can be revoked with $user->tokens()->delete().
Rule of thumb: browser app you control, use cookies; everything else, use tokens. Both can coexist behind auth:sanctum. Do not store bearer tokens in localStorage for a web SPA if you can avoid it.
For per-token abilities and rate limits see the DEV3 snippet.