Laravel × React の認証処理 - Sanctum を使ったログイン機能の実装
背景
フロントエンド(React)とバックエンド(Laravel API)を分離して開発する際、
Sanctum を使った API 認証を適切に設定することが必要です。
このブログでは、Laravel Sanctum を使用したフロントエンド(React)とバックエンド(Laravel API)の認証処理 について解説します。
Sanctum を利用するための準備
Sanctum を利用することで、React(フロントエンド)と Laravel API(バックエンド)間の認証を簡単に実装できます。
以下の手順でセットアップを行います。
1. Sanctum のインストール
まず、Laravel に Sanctum をインストールします。
composer require laravel/sanctum
次に、Sanctum の設定ファイルを公開し、マイグレーションを適用します。
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
2. Sanctum の設定
app/Http/Kernel.php
にミドルウェアを追加(Laravel 9 以下のみ必要)
(1) 👉 Laravel 10 以降ではこの設定は不要です!
Laravel 10 以降では Sanctum のミドルウェアはデフォルトで含まれているため、追加する必要はありません。
Laravel 9 以下を使用している場合のみ、EnsureFrontendRequestsAreStateful
を api
グループに追加してください。
protected $middlewareGroups = [
'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, // Laravel 9 以下のみ
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
config/sanctum.php
の stateful
を修正
(2) 👉 Laravel 10 以降ではデフォルトで localhost
が含まれているため、この設定も不要
フロントエンド(React)と API のドメインが異なる場合、Sanctum を適切に機能させるため Laravel 9 以下では config/sanctum.php
の stateful
に localhost
を追加します。
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'localhost,127.0.0.1')),
config/cors.php
で変更
(3) CORS の設定を 👉 Laravel 10 以降でも supports_credentials
を true
に変更推奨
フロントエンド(React)からのリクエストを許可するために CORS の設定を修正します。
return [
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'], // フロントエンドのURL
'allowed_headers' => ['*'],
'supports_credentials' => true, // Laravel 10 でも変更
];
.env
の設定を修正
(4) Sanctum の認証が Cookie ベースで動作するよう、.env
ファイルの SESSION_DRIVER
を cookie
に設定し、CORS 設定と合わせます。
SESSION_DRIVER=cookie
SANCTUM_STATEFUL_DOMAINS=localhost:3000
SESSION_DOMAIN=localhost
Sanctum を利用したログイン API
app/Http/Controllers/API/AuthController.php
にログイン処理を追加します。
public function login(Request $request)
{
Log::info('login request', ['request' => $request->all()]);
$request->validate([
'email' => 'required|email',
'password' => 'required',
]);
$user = User::where('email', $request->email)->first();
if (!$user || !Hash::check($request->password, $user->password)) {
return response()->json(['message' => 'Unauthorized'], 401);
}
// Sanctum 用のトークン発行
$token = $user->createToken('auth_token')->plainTextToken;
return response()->json(['token' => $token], 200);
}
フロントエンド(React)からのログイン処理
React 側では、fetch
を使用してログイン API にリクエストを送ります。
const handleLogin = async (e: React.FormEvent) => {
e.preventDefault();
try {
// CSRF クッキーを取得(Sanctum用)
await fetch("http://localhost:9000/sanctum/csrf-cookie", {
credentials: "include",
});
// ログイン API を呼ぶ
const response = await fetch("http://localhost:9000/api/login", {
method: "POST",
credentials: "include", // Cookie を送る
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, password }),
});
const data = await response.json();
console.log(data);
if (response.ok) {
login(data.token);
navigate("/dashboard");
} else {
setError("ログインに失敗しました。");
}
} catch (err) {
console.error(err);
setError("通信エラーが発生しました。");
}
};
エラーと対処法
1. Laravel の CORS 設定が原因でリクエストがブロックされる
→ config/cors.php
の supports_credentials
を true
に設定する
'supports_credentials' => true,
createToken()
の返り値が accessToken
ではなく plainTextToken
になる
2. → createToken('auth_token')->plainTextToken
を使用する
fetch
のリクエストが 401 Unauthorized
になる
3. → sanctum/csrf-cookie
を先にリクエストする
await fetch("http://localhost:9000/sanctum/csrf-cookie", {
credentials: "include",
});
まとめ
- Sanctum をインストールし、API 認証を有効化
- Laravel の
config/cors.php
で CORS 設定を修正 - Sanctum 用の
plainTextToken
をフロントエンドで適切に取得 sanctum/csrf-cookie
をリクエストして CSRF トークンを取得- Laravel 10 以降ではミドルウェアの追加は不要
これで Laravel Sanctum を利用した React + Laravel のログイン認証機能 が完成しました!
Discussion