0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Laravel Sanctum × curl:SPA認証検証で発生した500エラーの原因と対応まとめ

Posted at

「ログインは成功するのに /api/me が500になる」
「Cookie送ってるのに未認証」
「キャッシュ消しても直らない」

この記事では、Reactと接続する前に Laravel だけで SPA認証を確認しようとした際に発生したエラーの記録をまとめています。
Laravel Sanctum の認証処理を curl で検証したところ、設定・コード・環境の3つの不整合が重なって動作しない状態に陥りました。
ここでは、その原因と解決までの手順を整理します。


概要:発生していた3つの問題

分類 内容 対応策
コード $request->user()->id に直接アクセス → nullでクラッシュ nullチェックを追加し401を返すよう修正
設定 .envSANCTUM_STATEFUL_DOMAINSlocalhost:8000 が抜けていた localhostと5173ポートを明記
環境 キャッシュやサーバープロセスが古い設定を保持 artisan全クリア+サーバー再起動

検証の目的

Reactとつなぐ前に、以下の手順で Laravel 側の認証処理を確認しました。

  1. /login にメールアドレスとパスワードをPOSTしてセッション確立
  2. 取得したCookieを利用して /api/me にアクセスし、ログイン中ユーザー情報を取得

このとき、次のようなエラーが発生しました。

  • 419 unknown status(CSRF失敗)
  • Empty reply from server(PHPクラッシュ)
  • 500 Internal Server Error(認証処理中にサーバー停止)

認証ルートとミドルウェアの設定

Laravelでは web.php は「セッションあり」、api.php は「セッションなし」を前提にしています。
Sanctum の SPA認証では Cookie を利用するため、APIルートにも web ミドルウェアを追加する必要があります。

// routes/api.php
Route::middleware(['api', 'web'])->group(function () {
  Route::middleware('auth:sanctum')->get('/me', function (Request $request) {
    if (!$request->user()) {
      return response()->json(['message' => 'Unauthenticated.'], 401);
    }

    return response()->json([
      'id' => $request->user()->id,
      'email' => $request->user()->email,
      'name' => $request->user()->name,
    ]);
  });
});

これを設定しないと、Sanctum はセッション Cookie を認識できず、$request->user() は常に null のままになります。


CookieとSessionの関係

  • Session: サーバー側でユーザーの状態を保持
  • Session Cookie: クライアントに保存されるセッションID

クライアントはリクエストごとにCookieを送信し、サーバーは対応するセッションを復元して認証を継続します。
この動作を担うのが web ミドルウェアです。SPA認証ではこれが欠かせません。


CSRFトークンの取り扱い

Sanctum ではログイン前に /sanctum/csrf-cookie にアクセスし、XSRF-TOKEN Cookieを取得します。
その値をヘッダーで送信する必要があります。

curl -i -b cookie.txt -c cookie.txt -X POST \
  -H "X-XSRF-TOKEN: eyJpdiI6InpFOW..." \
  -d "email=test@example.com&password=password" \
  http://localhost:8000/login
エラー 原因 対応
419 フォームデータで送信していた ヘッダー X-XSRF-TOKEN に変更
Empty reply %3D がURLエンコードされたまま %3D= にURLデコード
500 $request->user() が null nullチェックを追加

500エラーの原因

ログから以下のエラーを確認しました。

[ERROR] Attempt to read property 'id' on null

Sanctum のセッションが認識されず $request->user() が null のままアクセスしていたため、Laravelがクラッシュしていました。


修正内容とリセット手順

routes/api.php

Route::middleware(['api', 'web'])->group(function () {
  Route::middleware('auth:sanctum')->get('/me', fn (Request $r) =>
    $r->user()
      ? response()->json(['id' => $r->user()->id])
      : response()->json(['message' => 'Unauthenticated.'], 401)
  );
});

.env

SANCTUM_STATEFUL_DOMAINS=localhost:5173,127.0.0.1:5173,localhost:8000,127.0.0.1:8000

キャッシュのクリア

php artisan config:clear
php artisan route:clear
php artisan view:clear
php artisan cache:clear
php artisan clear-compiled

再起動と再ログイン

php artisan serve
rm cookie.txt
curl -X POST /login ...
curl -b cookie.txt http://localhost:8000/api/me

この手順で HTTP/1.1 200 OK が返るようになり、正常に認証情報を取得できました。


まとめと注意点

分類 ポイント
設定 SANCTUM_STATEFUL_DOMAINS にサーバー自身のドメインを含める
コード $request->user() の null チェックを追加
環境 変更後はサーバーを再起動しキャッシュをクリア
デバッグ Set-Cookie: が連続発行される場合はセッションが破棄されているサイン

React接続前に Laravel 単体で認証を検証する際、この内容が同様の問題に直面している方の参考になれば幸いです。


0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?