🌟

Laravel Sanctumを試す

2023/02/13に公開

Laravel Sanctum パッケージをインストール

composer install laravel/sanctum

サービスプロバイダに登録する

php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"

sanctumでトークンを管理するテーブルを作成

(usersテーブルを追加し、seederを流しておいてください。)

以下のファイルをマイグレーション

2019_12_14_000001_create_personal_access_tokens_table.php
 php artisan migrate
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('personal_access_tokens', function (Blueprint $table) {
            $table->id();
            $table->morphs('tokenable');
            $table->string('name');
            $table->string('token', 64)->unique();
            $table->text('abilities')->nullable();
            $table->timestamp('last_used_at')->nullable();
            $table->timestamp('expires_at')->nullable();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('personal_access_tokens');
    }
};

Sanctumで使うミドルウェアを登録します。

\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::classを使えるようにコメントを解除します。


    /**
     * The application's route middleware groups.
     *
     * @var array<string, array<int, class-string|string>>
     */
    protected $middlewareGroups = [
       // 省略
        'api' => [
            \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            'throttle:api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
    ];

Sanctumで使うHasApiTokensトレイトをUserモデルに設定します。

use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;
   // 省略 
}

トークンを発行するルートを追加

// SanctumでTokenの発行
Route::post('/tokens/create', \App\Http\Controllers\PostSanctumTokenController::class);

トークンを発行する処理を追加

php artisan make:controller PostSanctumTokenController
<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;

class PostSanctumTokenController extends Controller
{
    public const TOKEN_NAME = 'app_api_token';
    public function __invoke(Request $request)
    {
     
        $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([
                    'error' => 'no user in database'
            ]);
        }

       // Tokenを発行する
        return response()->json([
            'accessToken' => $user->createToken(self::TOKEN_NAME)->plainTextToken
        ]);
    }
}

Token発行を試す

usersテーブルに登録されているユーザーのパスワードをPOSTのパラメータとしてセットしてください

curl -X POST -d "email=yoko28@example.com&password=password"  http://localhost/api/tokens/create | jq

Token発行が成功するとaccessTokenが取得できます

% curl -X POST -d "email=yoko28@example.com&password=password"  http://localhost/api/tokens/create | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   102    0    60  100    42    378    264 --:--:-- --:--:-- --:--:--   666
{
  "accessToken": "8|fbnPn7vcZW4zwGOpd9yhtBykELXipiuOn7cvioeb"
}

Tokenがある場合にのみ、APIを叩ける設定をします。

// sanctumでのガード処理を追加
Route::middleware('auth:sanctum')->group(function() {
  Route::get('/users', GetAllUsersController::class);
  Route::get('/user/{id}', GetUserController::class);
  Route::post('/user/create', CreateUserController::class);
  Route::put('/user/update', UpdateUserController::class);  
});

ガードができてるか確認

accessTokenのトークンを設定しない場合

curl -X GET http://localhost/api/users
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
<!DOCTYPE html>    0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
<html lang="en" class="auto">
<!--
Symfony\Component\Routing\Exception\RouteNotFoundException: Route [login] not defined. in file /var/www/html/vendor/laravel/framework/src/Illuminate/Routing/UrlGenerator.php on line 467
// 省略

Authorization: Bearer にaccessTokenのトークンを設定した場合

curl -X GET http://localhost/api/users -H 'Authorization: Bearer 9|OnWRYrfG6BFMRtKO8TxDxZhmnu9o8Lr2oVi98Ofc' | jq
{
  "data": [
    {
      "id": 1,
      "last_name": "木村",
      "first_name": "修平",
      "email": "yoko28@example.com",
      "post_code": "4141463",
      "address_prefecture": "茨城県",
      "address_city": "江古田市",
      "address_street_address": "杉山町山本8-5-7",
      "address_building_number": "105",
      "phone_number": "0288-01-5786",
      "created_at": "2023-01-02T05:42:34.000000Z",
      "updated_at": "2023-01-02T05:42:34.000000Z"
    },
    {
      "id": 2,
      "last_name": "宮沢",
      "first_name": "花子",
      "email": "dnakajima@example.org",
      "post_code": "1266621",
      "address_prefecture": "高知県",
      "address_city": "西之園市",
      "address_street_address": "木村町伊藤1-4-2",
      "address_building_number": "101",
      "phone_number": "0270-219-436",
      "created_at": "2023-01-02T05:42:34.000000Z",
      "updated_at": "2023-01-02T05:42:34.000000Z"
    },
// 省略

まとめ

  1. Laravel Sanctumパッケージをインストールする
  2. Laravel Sanctumパッケージをサービスプロバイダに設定する
  3. Laravel Sanctumのクラスをミドルウェアに登録する
  4. Userモデルにトークン発行ができるようにHasApiTokensのtraitを追加
  5. トークン発行の処理とルートを追加
  6. トークン発行のガード処理を追加

Discussion