Closed6

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に以下のようにコードを追加します。

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認証をする技術記事を見つけたのでそれに則って実装していきます。

http://blog.livedoor.jp/nnmy/archives/55128977.html

https://www.divx.co.jp/media/techblog-221114

https://qiita.com/104dev/items/0787a81f7dda892ce86a

API 認証設定を追加する

User モデルに SanctumHasApiTokens クラスを追加します。

app/Models/User.php
<?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 認証設定を追加する。」という記述があるものの具体的な実装が書かれていなかったので雰囲気で入れてみる。

config/auth.php
'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
    'api' => [ // 追加
        'driver' => 'sanctum',
        'provider' => 'users',
    ],
],

auth.php にある providersに以下のように書かれているか確認してください。

config/auth.php
'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => env('AUTH_MODEL', App\Models\User::class),
    ],
],
このスクラップは1ヶ月前にクローズされました