Laravelの認証(Auth)機能を実装する

はじめに

Webアプリケーションにおいて、ユーザー認証は最も基本的かつ重要な機能の一つです。ユーザー登録、ログイン、パスワードリセット、権限管理などの機能を一から実装するのは、時間がかかるだけでなく、セキュリティリスクも伴います。

幸いなことに、Laravelは堅牢な認証システムを標準で提供しており、数行のコマンドで簡単に実装できます。この記事では、Laravelの認証機能の実装方法から応用までを解説していきます。

基本的な認証システムの実装

Laravel Breezeを使った実装(Laravel 8以降)

Laravel 8以降では、Laravel Breezeという軽量な認証スカフォールディングパッケージが用意されています。Breezeは、認証に必要な基本的な機能を提供します。

インストール手順

  1. Breezeパッケージのインストール
composer require laravel/breeze --dev
  1. Breezeのインストール
php artisan breeze:install
  1. 必要なnpmパッケージのインストールとビルド
npm install && npm run dev
  1. データベースマイグレーションの実行
php artisan migrate

これだけで、以下の機能が実装されます:

  • ユーザー登録
  • ログイン/ログアウト
  • パスワードリセット
  • メール認証
  • パスワード確認
  • セッション管理

Breezeでは、Bladeテンプレートとともに基本的なスタイリングがTailwind CSSで適用されています。

Laravel JetstreamによるリッチUI認証(Laravel 8以降)

より高度な機能を持つ認証システムが必要な場合、Laravel Jetstreamを使用できます。

インストール手順

  1. Jetstreamパッケージのインストール
composer require laravel/jetstream
  1. Jetstreamのインストール(Livewireスタック)
php artisan jetstream:install livewire

または、Inertia.jsスタックを使う場合:

php artisan jetstream:install inertia
  1. 必要なnpmパッケージのインストールとビルド
npm install && npm run dev
  1. データベースマイグレーションの実行
php artisan migrate

Jetstreamには以下の追加機能があります:

  • 二要素認証
  • ブラウザセッション管理
  • プロフィール管理
  • APIサポート
  • チーム管理(オプション)

従来のUI認証パッケージ(Laravel 7以前)

Laravel 7以前では、laravel/uiパッケージを使用して認証機能を実装していました:

composer require laravel/ui

# Bootstrap使用
php artisan ui bootstrap --auth

# Vue.js使用
php artisan ui vue --auth

# React使用
php artisan ui react --auth

# インストールと実行
npm install && npm run dev
php artisan migrate

認証の仕組みを理解する

認証関連のファイル構成

Breezeをインストールすると、以下のファイルが生成されます:

  • app/Models/User.php: ユーザーモデル
  • app/Http/Controllers/Auth/: 認証関連のコントローラ
  • resources/views/auth/: 認証関連のビュー
  • routes/auth.php: 認証関連のルート
  • config/auth.php: 認証の設定ファイル

ユーザーモデル

Userモデルは、Illuminate\Foundation\Auth\Userクラスを継承しており、以下のトレイトを使用しています:

use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

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

認証の仕組み

Laravelの認証システムは、「ガード」と「プロバイダ」という2つの主要な概念に基づいています:

  • ガード: リクエストをどのように認証するかを定義(セッション、トークンなど)
  • プロバイダ: ユーザーをどこから取得するかを定義(データベース、APIなど)

これらの設定はconfig/auth.phpで管理されています:

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
    'api' => [
        'driver' => 'token',
        'provider' => 'users',
    ],
],

'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => App\Models\User::class,
    ],
],

認証機能の使い方

コントローラでの認証

Laravelでは、コントローラからユーザー認証を簡単に扱えます:

// ログイン
public function login(Request $request)
{
    $credentials = $request->validate([
        'email' => 'required|email',
        'password' => 'required',
    ]);

    if (Auth::attempt($credentials)) {
        $request->session()->regenerate();
        return redirect()->intended('dashboard');
    }

    return back()->withErrors([
        'email' => 'The provided credentials do not match our records.',
    ]);
}

// ログアウト
public function logout(Request $request)
{
    Auth::logout();
    $request->session()->invalidate();
    $request->session()->regenerateToken();
    return redirect('/');
}

認証状態の確認

// 現在のユーザーを取得
$user = Auth::user();

// ユーザーがログインしているか確認
if (Auth::check()) {
    // ログイン済みの処理
}

ミドルウェアでルートを保護

認証が必要なルートを保護するには、authミドルウェアを使用します:

// 単一ルート
Route::get('/dashboard', function () {
    // ログインユーザーのみアクセス可能
})->middleware('auth');

// ルートグループ
Route::middleware(['auth'])->group(function () {
    Route::get('/dashboard', [DashboardController::class, 'index']);
    Route::get('/profile', [ProfileController::class, 'show']);
});

また、ゲスト(未認証)ユーザーのみがアクセスできるルートにはguestミドルウェアを使用します:

Route::get('/login', [AuthController::class, 'showLoginForm'])->middleware('guest');

応用:カスタム認証の実装

カスタムガードの作成

独自の認証ガードを実装するには:

  1. サービスプロバイダでガードを拡張
// app/Providers/AuthServiceProvider.php
public function boot()
{
    $this->registerPolicies();

    Auth::extend('jwt', function ($app, $name, array $config) {
        // JWTガードのインスタンスを返す
        return new JwtGuard(Auth::createUserProvider($config['provider']));
    });
}
  1. 設定の追加
// config/auth.php
'guards' => [
    // 既存のガード...
    'api' => [
        'driver' => 'jwt',
        'provider' => 'users',
    ],
],

複数ユーザーテーブルの認証

例えば、一般ユーザーと管理者を別々のテーブルで管理する場合:

  1. 管理者モデルの作成
php artisan make:model Admin -m
  1. 管理者モデルの設定
// app/Models/Admin.php
use Illuminate\Foundation\Auth\User as Authenticatable;

class Admin extends Authenticatable
{
    protected $fillable = [
        'name', 'email', 'password',
    ];

    protected $hidden = [
        'password', 'remember_token',
    ];
}
  1. 認証設定の更新
// config/auth.php
'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
    'admin' => [
        'driver' => 'session',
        'provider' => 'admins',
    ],
],

'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => App\Models\User::class,
    ],
    'admins' => [
        'driver' => 'eloquent',
        'model' => App\Models\Admin::class,
    ],
],
  1. 管理者認証の使用
// 管理者としてログイン
Auth::guard('admin')->attempt($credentials);

// 管理者用ミドルウェア
Route::middleware('auth:admin')->group(function () {
    // 管理者ルート
});

メール認証の実装

Laravel Breezeを使用すると、メール認証機能も簡単に実装できます。

メール認証の有効化

  1. app/Models/User.phpMustVerifyEmailインターフェースを実装
use Illuminate\Contracts\Auth\MustVerifyEmail;

class User extends Authenticatable implements MustVerifyEmail
{
    // ...
}
  1. ルートの更新
// routes/web.php
use Illuminate\Foundation\Auth\EmailVerificationRequest;

// メール認証ルート
Route::get('/email/verify', function () {
    return view('auth.verify-email');
})->middleware('auth')->name('verification.notice');

Route::get('/email/verify/{id}/{hash}', function (EmailVerificationRequest $request) {
    $request->fulfill();
    return redirect('/home');
})->middleware(['auth', 'signed'])->name('verification.verify');

Route::post('/email/verification-notification', function (Request $request) {
    $request->user()->sendEmailVerificationNotification();
    return back()->with('message', 'Verification link sent!');
})->middleware(['auth', 'throttle:6,1'])->name('verification.send');
  1. ミドルウェアの適用

メール認証が必要なルートにはverifiedミドルウェアを適用します:

Route::get('/profile', function () {
    // メール認証済みのユーザーのみアクセス可能
})->middleware(['auth', 'verified']);

ソーシャルログインの実装

Laravel Socialiteを使用すると、OAuth認証(Google、Facebook、TwitterなどのSNSログイン)を簡単に実装できます。

Socialiteのインストール

composer require laravel/socialite

設定

  1. サービス設定の追加
// config/services.php
'github' => [
    'client_id' => env('GITHUB_CLIENT_ID'),
    'client_secret' => env('GITHUB_CLIENT_SECRET'),
    'redirect' => 'http://example.com/auth/github/callback',
],
  1. ルートの定義
// routes/web.php
use Laravel\Socialite\Facades\Socialite;

Route::get('/auth/github', function () {
    return Socialite::driver('github')->redirect();
});

Route::get('/auth/github/callback', function () {
    $githubUser = Socialite::driver('github')->user();
    
    $user = User::updateOrCreate([
        'github_id' => $githubUser->id,
    ], [
        'name' => $githubUser->name,
        'email' => $githubUser->email,
        'github_token' => $githubUser->token,
        'github_refresh_token' => $githubUser->refreshToken,
    ]);
 
    Auth::login($user);
 
    return redirect('/dashboard');
});

APIトークン認証

Laravel Sanctumを使用すると、APIトークン認証を簡単に実装できます。

Sanctumのインストール

composer require laravel/sanctum

Sanctumのインストールとマイグレーション:

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

ユーザーモデルの設定

// app/Models/User.php
use Laravel\Sanctum\HasApiTokens;

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

トークンの発行と認証

// トークンの発行
public function login(Request $request)
{
    $request->validate([
        'email' => 'required|email',
        'password' => 'required',
    ]);

    $user = User::where('email', $request->email)->first();

    if (! $user || ! Hash::check($request->password, $user->password)) {
        throw ValidationException::withMessages([
            'email' => ['The provided credentials are incorrect.'],
        ]);
    }

    return $user->createToken('auth-token')->plainTextToken;
}

// ルートの保護
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
    return $request->user();
});

セキュリティのベストプラクティス

1. CSRF保護

Laravelは自動的にCSRF保護を提供しています。フォームにはCSRFトークンを含める必要があります:

<form method="POST" action="/profile">
    @csrf
    <!-- フォームフィールド -->
</form>

2. パスワードのハッシュ化

Laravelはデフォルトでパスワードをハッシュ化します:

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

3. レート制限

ブルートフォース攻撃を防ぐためにレート制限を設定:

// routes/web.php
Route::post('/login', [AuthController::class, 'login'])
    ->middleware('throttle:5,1'); // 1分間に5回までの試行を許可

4. セッションセキュリティ

セッション設定を確認し、必要に応じてconfig/session.phpを更新します。HTTPSを強制する場合:

'secure' => env('SESSION_SECURE_COOKIE', true),

まとめ

Laravelは、堅牢で使いやすい認証システムを提供しています。基本的な認証機能からソーシャルログイン、APIトークン認証まで、幅広いニーズに対応できる柔軟性を持っています。

この記事で紹介した機能を活用して、安全で使いやすい認証システムをLaravelアプリケーションに実装してみてください。認証はセキュリティの要となる部分ですので、常に最新のベストプラクティスを取り入れながら実装することをお勧めします。

Laravelのエコシステムを活用することで、セキュアで機能的な認証システムを短時間で構築できることがLaravelの大きな強みの一つです。

コメント

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