Ваше API на Laravel работает.
Ваши учетные данные верны.
/sanctum/csrf-cookie может даже возвращать 204 .
Затем вы отправляете запрос на вход:
POST /login
и Laravel отвечает:
419 Page Expired
Если вы меняли случайные настройки CORS в надежде, что ошибка исчезнет, остановитесь.
Ошибка Laravel Sanctum 419 обычно связана с проблемами CSRF или сессионной аутентификации, и самый быстрый способ исправить ее — точно определить, на каком этапе ломается поток аутентификации Sanctum.
Вот порядок отладки, который я использую.
Кратко (TL;DR)
Для SPA-аутентификации в Laravel Sanctum проверьте следующие пять вещей:
1. Stateful middleware
2. SANCTUM_STATEFUL_DOMAINS
3. CORS credentials
4. Session cookies
5. Axios CSRF handling
И всегда отправляйте запрос:
GET /sanctum/csrf-cookie
перед:
POST /login
Если хотя бы одно звено в этой цепочке настроено неверно, Laravel может ответить ошибкой 419 CSRF token mismatch / Page Expired.
1. Поймите, что на самом деле означает ошибка 419
При использовании SPA-аутентификации в Laravel Sanctum Laravel полагается на обычные куки сессий и защиту от CSRF.
Взаимодействие с браузером выглядит примерно так:
Frontend
|
| GET /sanctum/csrf-cookie
v
Laravel
|
| Sets XSRF-TOKEN
| Sets session cookie
v
Browser
|
| POST /login
| Cookie + X-XSRF-TOKEN
v
Laravel validates request
Когда Laravel не может проверить эту связь между CSRF и сессией, вы можете получить:
419 Page Expired
Так что вопрос звучит не просто как:
"Правильна ли моя конфигурация CORS?"
Лучший вопрос:
"На каком именно этапе ломается цепочка аутентификации?"
2. Начните с панели Network в браузере
Прежде чем менять .env , Axios или конфигурацию Laravel, откройте:
Chrome DevTools → Network
Затем выполните вход повторно.
Найдите первый запрос, который ведет себя не так, как ожидалось.
Случай А: Ошибка OPTIONS
Если браузер блокирует запрос OPTIONS , в первую очередь исследуйте CORS.
Случай Б: Ошибка /sanctum/csrf-cookie
Ваш браузер не может успешно инициализировать защиту Sanctum от CSRF.
Случай В: Запрос CSRF успешен, но /login возвращает 419
Здесь я бы проверил:
-
XSRF-TOKEN - Куки сессии Laravel
-
X-XSRF-TOKEN - Домен кук
- Учетные данные в Axios
- Stateful-домены Sanctum
Случай Г: Вход успешен, но /api/user возвращает 401
Теперь проблема, скорее всего, связана с аутентифицированной сессией или с тем, что Sanctum не распознает запрос как stateful.
Эта простая классификация избавляет от множества лишних поисков ошибок.
3. Убедитесь, что Sanctum считает SPA stateful-приложением
Современные приложения на Laravel могут включать stateful API middleware для Sanctum в файле bootstrap/app.php .
Например:
use Illuminate\Foundation\Configuration\Middleware;
->withMiddleware(function (Middleware $middleware): void {
$middleware->statefulApi();
})
Это важно, потому что Sanctum должен понимать, что запросы от вашего собственного SPA должны использовать аутентификацию на основе сессий.
Если вы следуете старому руководству по Laravel, вы можете увидеть инструкции с упоминанием:
app/Http/Kernel.php
Будьте осторожны.
Структура приложения Laravel эволюционировала, поэтому старые туториалы по Sanctum могут указывать на файлы конфигурации, которые не подходят для новых приложений Laravel.
4. Проверьте SANCTUM_STATEFUL_DOMAINS
Предположим, ваша конфигурация выглядит так:
Frontend:
https://app.example.com
API:
https://api.example.com
Хост вашего SPA должен распознаваться как stateful.
Например:
SANCTUM_STATEFUL_DOMAINS=app.example.com
Одна из распространенных ошибок — добавление протокола:
SANCTUM_STATEFUL_DOMAINS=https://app.example.com
Обычно здесь требуется совсем не это.
Думайте о хосте, а не об URL фронтенда.
Локальный хост (localhost) может быть еще сложнее
Допустим, Vite запускается на:
http://localhost:5173
Тогда вам может понадобиться:
SANCTUM_STATEFUL_DOMAINS=localhost:5173
Не смешивайте бездумно:
localhost
127.0.0.1
localhost:5173
127.0.0.1:5173
Используйте одну и ту же схему для разработки.
Удивительное количество багов в Sanctum происходит из-за мельчайших различий в именах хостов.
5. CORS должен разрешать учетные данные (credentials)
Если ваша SPA-аутентификация использует куки, конфигурация CORS должна разрешать запросы с учетными данными.
Типичная конфигурация может включать:
return [
'paths' => [
'api/*',
'sanctum/csrf-cookie',
'login',
'logout',
],
'allowed_methods' => ['*'],
'allowed_origins' => [
'https://app.example.com',
],
'allowed_headers' => ['*'],
'supports_credentials' => true,
];
Важный параметр:
'supports_credentials' => true,
И не делайте так бездумно:
'allowed_origins' => ['*']
когда вы полагаетесь на куки с учетными данными.
Укажите origin фронтенда явно:
https://app.example.com
Origin и домен — это не одно и то же
Для CORS:
https://app.example.com
— это origin (источник).
Схема имеет значение.
Это разные origins:
http://app.example.com
https://app.example.com
Между тем, настройка stateful-доменов в Sanctum относится к нужному хосту/домену.
Смешение этих понятий — одна из причин, почему конфигурация Sanctum поначалу кажется запутанной.
6. Проверьте конфигурацию кук сессии
Теперь предположим, что ваша архитектура такова:
app.example.com
api.example.com
Обе находятся под управлением:
example.com
Типичная конфигурация сессии для продакшена может включать:
SESSION_DOMAIN=.example.com
SESSION_SECURE_COOKIE=true
SESSION_SAME_SITE=lax
Конфигурация кук для родительского домена позволяет сессии работать на соответствующих субдоменах.
После изменения настроек окружения также помните, что закэшированная конфигурация может заставить вас думать, что изменения не работают.
В зависимости от вашего рабочего процесса деплоя, вовремя очищайте кэш конфигурации Laravel.
Например:
php artisan config:clear
и пересоздавайте кэш конфигурации в соответствии с вашим процессом деплоя на продакшен.
7. Правильно настройте Axios
Ваша настройка Laravel может быть идеальной и все равно выдавать ошибку, если фронтенд никогда не отправляет куки обратно.
Для Axios:
import axios from 'axios';
const api = axios.create({
baseURL: import.meta.env.VITE_API_URL,
withCredentials: true,
withXSRFToken: true,
headers: {
Accept: 'application/json',
},
});
Перед входом в систему:
await api.get('/sanctum/csrf-cookie');
await api.post('/login', {
email,
password,
});
Два важных параметра Axios:
withCredentials: true
и:
withXSRFToken: true
Теперь загляните в браузер.
После:
GET /sanctum/csrf-cookie
вы обычно должны видеть соответствующие CSRF/сессионные куки.
Затем проверьте:
POST /login
и убедитесь, что данные аутентификации действительно отправляются обратно в Laravel.
Лучший способ отладки ошибки 419
Вместо того чтобы одновременно менять Laravel, CORS, Axios, куки и middleware, используйте эту последовательность.
Тест 1 — CSRF-эндпоинт
Запрос:
GET /sanctum/csrf-cookie
Ожидаемый результат:
Successful response
+
XSRF/session cookies created
Если куки не появляются, пока не отлаживайте контроллер входа.
Тест 2 — Запрос на вход
Запрос:
POST /login
Проверьте:
Are cookies attached?
Is X-XSRF-TOKEN present?
Is the request being blocked by CORS?
Если ответ отрицательный, вы существенно сузили круг поиска проблемы.
Тест 3 — Эндпоинт, требующий аутентификации
После успешного входа:
GET /api/user
Если вход прошел успешно, но этот запрос возвращает:
401 Unauthenticated
сосредоточьтесь на:
Sanctum stateful configuration
Session cookie
Cookie domain
withCredentials
Middleware
а не на CSRF.
419 против 401 против 422
Эти ошибки часто путают друг с другом.
419
Обычно проверяйте:
CSRF
XSRF token
Cookies
Session
401
Обычно проверяйте:
Authentication
Session recognition
Sanctum stateful requests
Missing credentials
422
Обычно проверяйте:
Validation errors
Missing fields
Invalid input
Понимание разницы может сэкономить поразительно много времени.
Почему Sanctum работает в Postman, но падает в Chrome?
Это крайне распространенная ситуация:
Postman ✅
Browser ❌
И это важный знак.
Браузеры применяют:
- CORS
- политики работы с куки
- origins (источники)
- учетные данные
- поведение SameSite
- CSRF-потоки
API-клиенты вроде Postman ведут себя совсем не так, как страница в браузере.
Поэтому, если API работает из Postman, но выдает ошибку из React/Vue/Vite, начинайте исследовать поток аутентификации в браузере, а не учетные данные вашей базы данных.
Не «исправляйте» ошибку 419 отключением CSRF
Вы можете найти в сети решения, предлагающие исключить эндпоинт входа из защиты CSRF.
Это может заставить ошибку исчезнуть.
Но это не обязательно означает, что вы починили Sanctum.
Для сессионной аутентификации в собственном SPA лучшим решением является правильная настройка:
CSRF
Session cookies
Stateful domains
CORS
Frontend credentials
а не удалять защиту, которая обнажила проблему с конфигурацией.
Одна важная деталь архитектуры продакшена, которую часто упускают
Эта настройка:
app.example.com
api.example.com
сильно отличается от:
my-app.vercel.app
api.example.com
В первом примере фронтенд и бэкенд используют один и тот же сайт верхнего уровня.
Во втором — они находятся на несвязанных доменах.
CORS не может волшебным образом превратить несвязанные домены в единое окружение first-party cookies.
Поэтому, если вы боретесь с аутентификацией на основе cookies в Sanctum на совершенно разных продакшн-доменах, пересмотрите саму архитектуру.
Кастомный домен фронтенда, такой как:
app.example.com
может сделать настройку first-party для Sanctum значительно более аккуратной.
Мой чек-лист для Sanctum 419 за 60 секунд
Прежде чем снова искать в Stack Overflow, проверьте это:
[ ] statefulApi() enabled
[ ] SPA exists in SANCTUM_STATEFUL_DOMAINS
[ ] Exact frontend origin allowed by CORS
[ ] supports_credentials = true
[ ] Correct SESSION_DOMAIN
[ ] Secure cookie configuration matches HTTPS setup
[ ] Axios withCredentials = true
[ ] Axios withXSRFToken = true
[ ] /sanctum/csrf-cookie called before login
[ ] XSRF-TOKEN appears in browser
[ ] Session cookie appears in browser
[ ] Login request sends cookies
[ ] X-XSRF-TOKEN is sent correctly
Если все двенадцать пунктов верны, вы исключили большинство частых причин ошибки 419 в Laravel Sanctum.
Порядок отладки важнее самого исправления
Главный урок заключается вовсе не в конкретной настройке в .env .
А в следующем:
Отлаживайте первый сломанный запрос, вместо того чтобы наугад менять конфигурацию аутентификации.
Используйте следующий порядок:
OPTIONS
↓
/sanctum/csrf-cookie
↓
Cookies
↓
POST /login
↓
/api/user
Найдите, где прекращается ожидаемое поведение.
Обычно именно там и начинается ваша настоящая проблема.
Нужен полный справочник по ошибке 419 в Laravel Sanctum?
Я написал более подробное руководство, охватывающее Laravel Sanctum CORS, CSRF-cookies, настройку Axios, продакшн-домены, проблемы с localhost, настройку сессий, ошибки 401 против 419 против 422, а также устранение неполадок при деплое.
👉 Читайте полное руководство по исправлению ошибки CORS 419 в Laravel Sanctum
Используйте полное руководство, если быстрый чек-лист выше не помог сразу выявить проблему.
Если вы занимаетесь отладкой Sanctum прямо сейчас, помните:
419 — это симптом. Поток запросов браузера подскажет вам причину.
Комментарии (0)
Пока нет комментариев — будьте первым.