0.この記事の目的
LaravelでSanctumを使ってAPIログインを実装しているのに、ログインがうまくいかず 500 Internal Server Error
や 401 Unauthorized
が返ってきて困ったことはありませんか?
本記事では、実際に私がハマった原因とその解決方法を紹介します。
1.背景
バックエンド:Laravel
フロントエンド:React
インフラ:Docker / Mysql
上記構成でWebアプリを作成中、Laravel Sanctumを使用してAPIログインを確認していたところ、ログイン処理のみ
エラーが発生。Postmanでリクエストを確認しながら解決まで至った手順をまとめました。
該当コード抜粋
api.php
*ユーザ登録画面表示:正常
*ユーザ登録:正常
*ログイン画面表示:正常
*ログイン処理:エラー発生
Route::prefix('/user')->group(function () {
Route::prefix('/register')->group(function () {
Route::get('/', [AuthController::class, 'showRegister']); // ユーザ登録画面表示
Route::post('/', [AuthController::class, 'register']); //ユーザ登録処理
});
Route::prefix('/login')->group(function () {
Route::get('/', [AuthController::class, 'showLogin']); // ログイン画面表示
Route::post('/', [AuthController::class, 'login']); // ログイン処理
});
controller
(ログイン処理)
// ログイン処理
public function login(LoginRequest $request)
{
$user = User::where('email', $request->email)->first();
if (!$user || !Hash::check($request->password, $user->password)) {
return response()->json(['message' => '認証失敗'], 401);
}
$token = $user->createToken('auth_token')->plainTextToken;
return response()->json([
'message' => 'ログイン成功',
'token' => $token,
'user' => [
'id' => $user->id,
'name' => $user->name,
'email' => $user->email,
'avatar_path' => $user->avatar_path,
],
]);
}
2.エラー内容
/api/user/login に POST リクエストを送ると、以下のような現象が発生。
・レスポンス:500 Internal Server Error
・ログ:Call to undefined method App\Models\User::createToken()
3.結論
Userモデルに HasApiTokens がないとログインできない!
・Laravel Sanctum を使ってトークン認証を行う際には、ログイン時に以下のようにトークンを発行します。
$token = $user->createToken('auth_token')->plainTextToken;
・この createToken() メソッドは、HasApiTokens
というトレイトを使っている必要があります。
4.解決方法
User.php モデルに HasApiTokens
を追加
※抜粋内容
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasFactory, Notifiable, SoftDeletes, HasApiTokens;
・これで createToken() が有効になり、トークンを発行できるようになります。
5.まとめ
Laravelでログインできない時は
・Userモデルに HasApiTokens
があるか?
*createToken()
を使うにはこれが必要。
・パスワードがハッシュ化されているか?
*プレーンな文字列のままだと Hash::check() が失敗する。
・ルーティングでSanctum関連のミドルウェアを使用しているか?
*Sanctumトークン認証を使用するにはauth:sanctum
を使う(1.背景 api.php 参照)
・エラーログは確認したか?
*500エラーが出る場合、画面だけで原因が分からないためログファイルの以下のコマンドでログ確認が必要。
※対象のdockerコンテナ内で
tail -f storage/logs/laravel.log