【Laravel】419 CSRF token mismachエラーの対処記録
Laravel Sanctumを使ってログイン機能を実装中にエラーに遭遇。 思考の整理と次に時間を溶かさないようにするためのメモ
結論
.env
での SESSION_DOMAIN='localhost'
ここが間違えていた。
.env にてセッションを設定するドメインを設定しているので、ドメインを設定する。
開発環境なので localhost
で良い。
本番環境のドメインを指定してしまっていたので、セッションクッキーがセットされていなかったよう。考えてみれば当たり前。デプロイ時は本番のドメインを指定する。
ちなみに localhost:8000
だとエラーになるのでポート番号はいらない!
環境
Sanctumによるログインの流れ
- Laravel Sanctumをインストール
- 自動で
sanctum/csrf-cookie
というルーティングが追加されるから、ここにGETリクエストすることで、CSRF保護を初期化する。(/login
へPOSTする前に必ず実行する必要あり。これを行わないと、CSRFが照合できずエラーになる ) - レスポンスヘッダーに
XSRF-TOKEN
というクッキーが返ってくる。 - これを
X-XSRF-TOKEN
というキーでリクエストヘッダーにセットして、/login
へリクエストする。 $request->session()->regenerate();
でフロントにセッションクッキーをセット。
流れは間違っていなかったが、ドメインが間違えていたのでセッションクッキーをセットできていなかった。
調べたあれこれ
guard
// config/auth.php 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'token', // 'driver' => 'session', 'provider' => 'users', 'hash' => false, ], ],
- Laravel Sanctumによる認証は、webのguardを使用する。
- regiter、login、logoutあたりはセッションクッキーを使用するので、sessionドライバーを設定しているweb guardを使用する。
- api guardはデフォルトではtokenドライバーが設定されている。これをsessionに書き換えてもいいようだけど、それだと本来のAPIの仕様が薄れちゃうから微妙という記事もあった。
- 書き換えてみたら CSRF token mismachエラーはでなくなったものの、
Auth::attempt()
が使用できなくなり断念。undefind
エラーが出た。やっぱりセッションクッキーだからapiではなくてwebの方を使えということなのかな?
CSRF
\App\Http\Middleware\VerifyCsrfToken::class
の箇所でtokenの検証をしている。- フロントから送られてくる
X-XSRF-TOKEN
とLaravel側のトークンを比べている。
// app/Http/Kernel.php protected $middlewareGroups = [ 'web' => [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, // \Illuminate\Session\Middleware\AuthenticateSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, ←ここ \Illuminate\Routing\Middleware\SubstituteBindings::class, ], 'api' => [ \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, 'throttle:api', \Illuminate\Routing\Middleware\SubstituteBindings::class, ], ];
VerifyCsrfToken
クラスの詳しい動きは下記の記事が細かく載っていた。
LaravelのCSRF対策の処理を実際のコードから見てみる - Qiita
その他
- config/cors.phpに下記を追記。
// config/cors.php 'paths' => [ 'api/*', 'login', // 追記 'logout', // 追記 'register', // 追記 'sanctum/csrf-cookie' ], 'supports_credentials' => true,
参考
Laravel7 + Sanctum でSPAログイン認証機能を実装 - Qiita
Laravel API SanctumでSPA認証する - Qiita
【attemptメソッドが使えない?】Call to undefined method TokenGuard::attempt() の解決法
Laravelの標準Authentication(Auth)の動きを調べてみる - Qiita
Laravel5.4でAuth::attemptを使わずに認証処理をカスタマイズ