第6回 認証と認可の導入

Laravel WebAPI開発

こんにちは、PHP開発者の皆さん!この連載の第6回では、Laravel 10を使ってAPIの認証と認可を実装する方法について詳しく解説します。APIの認証と認可は、ユーザーの安全なアクセスを確保し、リソースへのアクセス制御を行うために重要です。それでは、始めましょう!

1. Laravel Passportのインストール

Laravelでは、APIの認証を簡単に行うためのパッケージとしてLaravel Passportを提供しています。まず、Passportをインストールしましょう。

パッケージのインストール

以下のコマンドを実行してLaravel Passportをインストールします。

./vendor/bin/sail composer require laravel/passport
Bash

Passportの設定

次に、Passportの設定を行います。以下のコマンドを実行してPassportのマイグレーションを実行し、必要なデータベーステーブルを作成します。

./vendor/bin/sail artisan migrate
Bash

その後、Passportのインストールを実行します。

./vendor/bin/sail artisan passport:install
Bash

これにより、暗号鍵とクライアントが生成されます。

認証ドライバーの設定

config/auth.php ファイルを開き、API認証ドライバーをPassportに設定します。

config/auth.php
'guards' => [
    'api' => [
        'driver' => 'passport',
        'provider' => 'users',
    ],
],
PHP

Passportのサービスプロバイダーを登録

app/Providers/AuthServiceProvider.php ファイルを開き、Passportのサービスプロバイダーを登録します。

app/Providers/AuthServiceProvider.php
namespace App\Providers;

use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Laravel\Passport\Passport;

class AuthServiceProvider extends ServiceProvider
{
    public function boot()
    {
        $this->registerPolicies();

        Passport::routes();
    }
}
PHP

2. ユーザー認証の実装

次に、ユーザー認証用のエンドポイントを作成します。これには、ユーザーの登録、ログイン、ログアウト機能が含まれます。

ユーザー登録

ユーザー登録用のコントローラメソッドを作成します。app/Http/Controllers/Api/AuthController.php を作成し、以下のコードを追加します。

app/Http/Controllers/Api/AuthController.php
namespace App\Http\Controllers\Api;

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

class AuthController extends Controller
{
    public function register(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:users',
            'password' => 'required|string|min:8',
        ]);

        if ($validator->fails()) {
            return response()->json($validator->errors(), 400);
        }

        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password),
        ]);

        $token = $user->createToken('LaravelPassportToken')->accessToken;

        return response()->json(['token' => $token], 201);
    }
}
PHP

ユーザーログイン

次に、ログイン用のメソッドを追加します。

app/Http/Controllers/Api/AuthController.php
public function login(Request $request)
{
    $validator = Validator::make($request->all(), [
        'email' => 'required|string|email',
        'password' => 'required|string',
    ]);

    if ($validator->fails()) {
        return response()->json($validator->errors(), 400);
    }

    $credentials = $request->only('email', 'password');

    if (!auth()->attempt($credentials)) {
        return response()->json(['message' => 'Unauthorized'], 401);
    }

    $user = auth()->user();
    $token = $user->createToken('LaravelPassportToken')->accessToken;

    return response()->json(['token' => $token], 200);
}
PHP

ユーザーログアウト

ログアウト用のメソッドも追加します。

app/Http/Controllers/Api/AuthController.php
public function logout(Request $request)
{
    $request->user()->token()->revoke();

    return response()->json(['message' => 'Successfully logged out'], 200);
}
PHP

3. 認証用のルート設定

次に、API用の認証ルートを設定します。routes/api.php ファイルに以下のコードを追加します。

routes/api.php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Api\AuthController;

Route::post('register', [AuthController::class, 'register']);
Route::post('login', [AuthController::class, 'login']);

Route::middleware('auth:api')->group(function () {
    Route::post('logout', [AuthController::class, 'logout']);
});
PHP

4. 認可の実装

認可は、ユーザーが特定のリソースにアクセスできるかどうかを制御します。Laravelでは、ポリシーを使って認可を実装します。

ポリシーの作成

以下のコマンドを実行してポリシーを生成します。

./vendor/bin/sail artisan make:policy PostPolicy --model=Post
Bash

生成されたポリシーを開き、必要なメソッドを追加します。例えば、投稿の編集を許可するかどうかを確認するメソッドを追加します。

namespace App\Policies;

use App\Models\Post;
use App\Models\User;

class PostPolicy
{
    public function update(User $user, Post $post)
    {
        return $user->id === $post->user_id;
    }

    public function delete(User $user, Post $post)
    {
        return $user->id === $post->user_id;
    }
}
PHP

ポリシーの登録

ポリシーを登録するために、app/Providers/AuthServiceProvider.php ファイルを編集します。

app/Providers/AuthServiceProvider.php
use App\Models\Post;
use App\Policies\PostPolicy;

protected $policies = [
    Post::class => PostPolicy::class,
];
PHP

ポリシーの適用

ポリシーを適用するために、コントローラメソッドでauthorizeメソッドを使用します。例えば、投稿の更新を制御するupdateメソッドにポリシーを適用します。

PHP
namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Requests\StorePostRequest;
use App\Models\Post;

class PostController extends Controller
{
    public function update(StorePostRequest $request, $id)
    {
        $post = Post::findOrFail($id);

        $this->authorize('update', $post);

        $post->update($request->validated());

        return response()->json($post, 200);
    }

    public function destroy($id)
    {
        $post = Post::findOrFail($id);

        $this->authorize('delete', $post);

        $post->delete();

        return response()->json(['message' => 'Post deleted successfully'], 204);
    }
}
PHP

5. APIテストの更新

最後に、認証と認可が正しく機能することを確認するために、APIテストを更新します。例えば、ログインテストを追加します。

PHP
namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
use App\Models\User;

class AuthApiTest extends TestCase
{
    use RefreshDatabase;

    public function test_can_register()
    {
        $data = [
            'name' => 'Test User',
            'email' => 'test@example.com',
            'password' => 'password',
        ];

        $response = $this->postJson('/api/register', $data);

        $response->assertStatus(201)
                 ->assertJsonStructure(['token']);
    }

    public function test_can_login()
    {
        $user = User::factory()->create([
            'password' => bcrypt($password = 'password'),
        ]);

        $data = [
            'email' => $user->email,
            'password' => $password,
        ];

        $response = $this->postJson('/api/login', $data);

        $response->assertStatus(200)
                 ->assertJsonStructure(['token']);
    }

    public function test_can_logout()
    {
        $user = User::factory()->create();
        $token = $user->createToken('LaravelPassportToken')->accessToken;

        $response = $this->withHeaders([
            'Authorization' => "Bearer $token",
        ])->postJson('/api/logout');

        $response->assertStatus(200);
    }
}
PHP

この記事では、Laravel 10を使ってAPIの認証と認可を実装する方法について解説しました。ユーザー認証にLaravel Passportを使用し、ポリシーを利用してリソースへのアクセス制御を行いました。次回は、APIのテストとドキュメント作成について学びます。それでは、次の記事でお会いしましょう!

次の記事: 第7回 データのシリアライズとリソースの変換

コメント

タイトルとURLをコピーしました