Для власного SPA (Vue, React) Sanctum пропонує не токени, а звичайну сесію Laravel з cookie. Токен у JavaScript не потрапляє взагалі - XSS не зможе його вкрасти, а вихід знищує сесію на сервері.
Умова: SPA і API - на одному домені верхнього рівня (можна різні піддомени: app.example.com і api.example.com).
Налаштування на бекенді:
// bootstrap/app.php
->withMiddleware(function (Middleware $middleware): void {
$middleware->statefulApi(); // сесія для запитів зі «своїх» доменів
})
SANCTUM_STATEFUL_DOMAINS=app.example.com
SESSION_DOMAIN=.example.com
statefulApi()додає в групуapimiddleware, що вмикає сесію й CSRF для запитів із доменів зі спискуstateful;SESSION_DOMAINз крапкою - cookie сесії доступна піддоменам;- CORS (
config/cors.php): дозволити домен SPA іsupports_credentials => true, бо браузер має надсилати cookie в міжсайтовий запит.
Вхід з SPA:
await fetch('https://api.example.com/sanctum/csrf-cookie', { credentials: 'include' });
await fetch('https://api.example.com/login', {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
'X-XSRF-TOKEN': decodeURIComponent(readCookie('XSRF-TOKEN')),
},
body: JSON.stringify({ email, password }),
});
/sanctum/csrf-cookieставить cookieXSRF-TOKEN;- вхід - звичайний маршрут логіну (Fortify, власний контролер з
Auth::attempt); - далі всі запити з
credentials: 'include'і тим самим заголовком CSRF; маршрути захищеніauth:sanctum.
Axios передає X-XSRF-TOKEN автоматично.
Як Sanctum розрізняє SPA і сторонніх клієнтів: за заголовками Origin/Referer. Якщо запит з домену зі списку stateful - сесія й CSRF; інакше - автентифікація токеном. Той самий auth:sanctum працює для обох.
Типові проблеми:
419 CSRF token mismatch- не викликано/sanctum/csrf-cookie, не передано заголовок або домен SPA не вstateful(порт теж має збігатися:localhost:5173);401після успішного входу - cookie не надсилається: немаєcredentials: 'include', неправильнийSESSION_DOMAINчиsupports_credentials;- різні домени (
app.comіapi.net) - cookie-автентифікація не працює; потрібні токени чи BFF.
Коли не підходить: мобільні застосунки й сторонні інтеграції - для них токени.
Докладніше в документації: Laravel Sanctum: автентифікація SPA