Laravel+Reactプロジェクトでsanctumを使用したユーザー認証を作成する
やりたいこと
Laravel+Reactプロジェクトでsanctumを使用したユーザー認証機能を実装したい。
参考記事
Laravel Sanctumをインストールする
composer require laravel/sanctum
./composer.json has been updated
Running composer update laravel/sanctum
Loading composer repositories with package information
Updating dependencies
Lock file operations: 0 installs, 1 update, 0 removals
- Upgrading laravel/sanctum (v4.0.2 => v4.0.3)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 0 installs, 1 update, 0 removals
- Downloading laravel/sanctum (v4.0.3)
- Upgrading laravel/sanctum (v4.0.2 => v4.0.3): Extracting archive
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi
INFO Discovering packages.
laravel/sail ..................................................................................................... DONE
laravel/sanctum .................................................................................................. DONE
laravel/tinker ................................................................................................... DONE
nesbot/carbon .................................................................................................... DONE
nunomaduro/collision ............................................................................................. DONE
nunomaduro/termwind .............................................................................................. DONE
79 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
> @php artisan vendor:publish --tag=laravel-assets --ansi --force
INFO No publishable resources for tag [laravel-assets].
No security vulnerability advisories found.
Using version ^4.0 for laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
INFO Publishing assets.
Copying directory [vendor/laravel/sanctum/database/migrations] to [database/migrations] .......................... DONE
File [config/sanctum.php] already exists ...................................................................... SKIPPED
php artisan migrate
INFO Running migrations.
2024_10_13_061938_create_personal_access_tokens_table ..................................................... 2.68ms FAIL
Illuminate\Database\QueryException
SQLSTATE[HY000]: General error: 1 table "personal_access_tokens" already exists (Connection: sqlite, SQL: create table "personal_access_tokens" ("id" integer primary key autoincrement not null, "tokenable_type" varchar not null, "tokenable_id" integer not null, "name" varchar not null, "token" varchar not null, "abilities" text, "last_used_at" datetime, "expires_at" datetime, "created_at" datetime, "updated_at" datetime))
at vendor/laravel/framework/src/Illuminate/Database/Connection.php:813
809▕ $this->getName(), $query, $this->prepareBindings($bindings), $e
810▕ );
811▕ }
812▕
➜ 813▕ throw new QueryException(
814▕ $this->getName(), $query, $this->prepareBindings($bindings), $e
815▕ );
816▕ }
817▕ }
+9 vendor frames
10 database/migrations/2024_10_13_061938_create_personal_access_tokens_table.php:14
Illuminate\Support\Facades\Facade::__callStatic()
+26 vendor frames
37 artisan:13
Illuminate\Foundation\Application::handleCommand()
エラーが発生しました。
SQLSTATE[HY000]: General error: 1 table "personal_access_tokens" already exists (Connection: sqlite, SQL: create table "personal_access_tokens" ("id" integer primary key autoincrement not null, "tokenable_type" varchar not null, "tokenable_id" integer not null, "name" varchar not null, "token" varchar not null, "abilities" text, "last_used_at" datetime, "expires_at" datetime, "created_at" datetime, "updated_at" datetime))
既にpersonal_access_tokens
があるためエラーを吐いているようです。ロールバックしてみましょう。
php artisan migrate:rollback
INFO Rolling back migrations.
2024_06_29_142908_create_todos_table ...................................................................... 9.96ms DONE
0001_01_01_000003_create_personal_access_tokens_table ..................................................... 8.16ms DONE
0001_01_01_000002_create_jobs_table ...................................................................... 14.70ms DONE
0001_01_01_000001_create_cache_table ..................................................................... 20.78ms DONE
0001_01_01_000000_create_users_table ..................................................................... 13.64ms DONE
php artisan migrate
INFO Running migrations.
0001_01_01_000000_create_users_table ..................................................................... 29.42ms DONE
0001_01_01_000001_create_cache_table ...................................................................... 7.80ms DONE
0001_01_01_000002_create_jobs_table ...................................................................... 25.92ms DONE
0001_01_01_000003_create_personal_access_tokens_table .................................................... 12.87ms DONE
2024_06_29_142908_create_todos_table ...................................................................... 4.83ms DONE
2024_10_13_061938_create_personal_access_tokens_table ..................................................... 0.45ms FAIL
Illuminate\Database\QueryException
SQLSTATE[HY000]: General error: 1 table "personal_access_tokens" already exists (Connection: sqlite, SQL: create table "personal_access_tokens" ("id" integer primary key autoincrement not null, "tokenable_type" varchar not null, "tokenable_id" integer not null, "name" varchar not null, "token" varchar not null, "abilities" text, "last_used_at" datetime, "expires_at" datetime, "created_at" datetime, "updated_at" datetime))
at vendor/laravel/framework/src/Illuminate/Database/Connection.php:813
809▕ $this->getName(), $query, $this->prepareBindings($bindings), $e
810▕ );
811▕ }
812▕
➜ 813▕ throw new QueryException(
814▕ $this->getName(), $query, $this->prepareBindings($bindings), $e
815▕ );
816▕ }
817▕ }
+9 vendor frames
10 database/migrations/2024_10_13_061938_create_personal_access_tokens_table.php:14
Illuminate\Support\Facades\Facade::__callStatic()
+26 vendor frames
37 artisan:13
Illuminate\Foundation\Application::handleCommand()
エラーが発生しました。そもそもpersonal_access_tokens
マイグレーションが二つあるようなので片方を削除しようと思います。
php artisan migrate:rollback
INFO Rolling back migrations.
2024_06_29_142908_create_todos_table .................................................................... 11.62ms DONE
0001_01_01_000003_create_personal_access_tokens_table .................................................... 6.57ms DONE
0001_01_01_000002_create_jobs_table ..................................................................... 15.46ms DONE
0001_01_01_000001_create_cache_table ..................................................................... 9.35ms DONE
0001_01_01_000000_create_users_table .................................................................... 15.31ms DONE
このタイミングで直接2024_10_13_061938_create_personal_access_tokens_table.php
を削除します。
削除したら再度マイグレーションを実行します。
php artisan migrate
INFO Running migrations.
0001_01_01_000000_create_users_table .................................................................... 38.03ms DONE
0001_01_01_000001_create_cache_table ..................................................................... 7.99ms DONE
0001_01_01_000002_create_jobs_table ..................................................................... 20.64ms DONE
0001_01_01_000003_create_personal_access_tokens_table ................................................... 11.58ms DONE
2024_06_29_142908_create_todos_table ..................................................................... 5.34ms DONE
無事マイグレーションができました。
Sanctumのマイグレーションを無効化する
Laravel8.6以降はsanctumが標準インストールされているようなので特に必要ありませんでした(下調べが甘かった...)。
今回はSPA認証を実装したいのでpersonal_access_tokens
のマイグレーションを削除したいと思います。
とりあえず一旦マイグレーションをロールバックします。
php artisan migrate:rollback
INFO Rolling back migrations.
2024_06_29_142908_create_todos_table ..................................................................... 9.17ms DONE
0001_01_01_000003_create_personal_access_tokens_table .................................................... 6.75ms DONE
0001_01_01_000002_create_jobs_table ..................................................................... 16.56ms DONE
0001_01_01_000001_create_cache_table .................................................................... 11.57ms DONE
0001_01_01_000000_create_users_table .................................................................... 17.15ms DONE
app/Providers/AppServiceProvider.php
に以下のようにコードを追加します。
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Laravel\Sanctum\Sanctum; // 追加
// Repositories
use App\Repositories\TodoRepository\TodoRepository;
use App\Repositories\TodoRepository\TodoRepositoryInterface;
// Services
use App\Services\TodoService\TodoService;
use App\Services\TodoService\TodoServiceInterface;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
Sanctum::ignoreMigrations(); // 追加
// Repositories
$this->app->bind(TodoRepositoryInterface::class, TodoRepository::class);
// Services
$this->app->bind(TodoServiceInterface::class, TodoService::class);
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
//
}
}
php artisan migrate:fresh
Error
Call to undefined method Laravel\Sanctum\Sanctum::ignoreMigrations()
at app/Providers/AppServiceProvider.php:21
17▕ * Register any application services.
18▕ */
19▕ public function register(): void
20▕ {
➜ 21▕ Sanctum::ignoreMigrations(); // 追加
22▕ // Repositories
23▕ $this->app->bind(TodoRepositoryInterface::class, TodoRepository::class);
24▕ // Services
25▕ $this->app->bind(TodoServiceInterface::class, TodoService::class);
+8 vendor frames
9 artisan:13
Illuminate\Foundation\Application::handleCommand()
Sanctum::ignoreMigrations()
なるものは存在しないようです。はて...?
API認証の準備をする
Laravel11でAPI認証をする技術記事を見つけたのでそれに則って実装していきます。
API 認証設定を追加する
User
モデルに Sanctum
の HasApiTokens
クラスを追加します。
<?php
namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens; // 追加
class User extends Authenticatable
{
use HasFactory, Notifiable, HasApiTokens; // 追加
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
}
}
「auth.php
に API 認証設定を追加する。」という記述があるものの具体的な実装が書かれていなかったので雰囲気で入れてみる。
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [ // 追加
'driver' => 'sanctum',
'provider' => 'users',
],
],
auth.php
にある providers
に以下のように書かれているか確認してください。
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => env('AUTH_MODEL', App\Models\User::class),
],
],
記事投稿
こちらのスクラップを元に記事を作成しました。
簡易的な実装なので引き続き実装していく。