L初めてのLaravel

Laravel 認証・認可フロー図解

「ログインの仕組み」と「権限チェック」を図でつかむ

Laravelのセキュリティは大きく2つに分かれます。認証(Authentication)は「あなたは誰か(ログイン済みか)」の確認、認可(Authorization)は「その人に、この操作をする権限があるか」の確認です。 ここではまず認証の流れをフロー図で追い、続いて認可(Gate と Policy)の 使い分けをコード例つきで整理します。

認証(Authentication)フロー

ログインフォームの送信から、Guard と User Provider による本人確認、 セッション確立、その後の auth ミドルウェアによる保護、ログアウトまでの流れです。

利用者・入力Guard(認証方式)User Providerセッション/rememberauth ミドルウェアログアウト
  1. ログインフォームemail / password を送信
  2. 認証情報(credentials)['email','password']
  3. Guard(認証方式)session / token
  4. User ProviderDBからユーザー取得
  5. パスワード照合Hash::check()
  6. セッション確立ログイン状態を保存
  7. remember me(任意)永続Cookieを発行
  8. auth ミドルウェアで保護未ログインは弾く
  9. ログアウトAuth::logout()

※ Guard が「どう識別するか」、User Provider が「どこから取り出して照合するか」を担当します。 Web画面は session ガード、APIは token ガード(Sanctumなど)が基本です。

登場する部品の役割

Guard(ガード)

「どうやってユーザーを識別するか」の方式です。Web画面はセッションで覚える session ガード、APIはリクエストごとにトークンを見る token ガードが基本。どのガードを使うかは config/auth.php で設定します。

  • config/auth.php (guards)
  • SessionGuard
  • TokenGuard
  • Auth::guard('web')

User Provider(ユーザープロバイダ)

「ユーザーをどこから、どう取り出すか」の担当です。送られた credentials を使ってDBから該当ユーザーを探し、パスワードのハッシュ照合まで行います。標準は Eloquent プロバイダ(App\Models\User を使用)。

  • config/auth.php (providers)
  • EloquentUserProvider
  • App\Models\User
  • Hash::check()

session(セッション)

認証に成功したら「このブラウザはログイン済み」という印をセッションに保存します。以降のリクエストはセッションのIDをCookieで送ることで、毎回ログインし直さずに済みます。remember me は別の永続Cookieで期限を延ばす仕組みです。

  • StartSession
  • config/session.php
  • Auth::login($user, $remember)
  • remember_token カラム

auth ミドルウェア

保護したいルートに付ける「関所」です。リクエストがログイン済みかをガードに問い合わせ、未ログインならログイン画面へリダイレクト(APIなら401)します。ルートやコントローラに ->middleware('auth') で付けます。

  • Authenticate ミドルウェア
  • Route::...->middleware('auth')
  • middleware('auth:sanctum')

認可(Authorization): Gate と Policy

認証で「ログイン済み」と分かった後、その人がこの操作をしてよいかを判定するのが認可です。判定ルールの置き場所としてGate と Policy の2つがあります。

観点Gate(ゲート)Policy(ポリシー)
何に対する権限か特定のモデルに紐づかない、単発・横断的な権限特定のモデル(例: Post)に対する一連の権限をまとめる
定義場所AuthServiceProvider の boot() で Gate::define(...)app/Policies/ 配下のポリシークラス(1モデル1クラス)
生成コマンド(手書きでクロージャを定義)php artisan make:policy PostPolicy --model=Post
向いている場面「管理者だけ」など、モデルに依存しない単純な判定「自分の投稿だけ編集可」など、モデル単位の複数操作
呼び出し例Gate::allows('admin-only')$user->can('update', $post)

呼び出し方の使い分け

$user->can(...)

使う場所:
コントローラ・任意のPHP
何をする:
権限があるかを true / false で返す(判定だけ)
権限なしなら:
false を返すだけ(例外は投げない)
if ($user->can('update', $post)) { /* ... */ }

@can(...) / @cannot(...)

使う場所:
Blade テンプレート
何をする:
権限の有無で表示を出し分ける(ボタンの表示制御など)
権限なしなら:
そのブロックを表示しないだけ
@can('update', $post) <a href="...">編集</a> @endcan

$this->authorize(...)

使う場所:
コントローラ(AuthorizesRequests)
何をする:
権限がなければ処理を止める(ガードとして使う)
権限なしなら:
403 (AuthorizationException) を投げる
$this->authorize('update', $post);

Gate::allows(...) / denies(...)

使う場所:
任意のPHP(ファサード)
何をする:
現在ログイン中のユーザーで権限を判定する
権限なしなら:
false / true を返すだけ(例外は投げない)
if (Gate::allows('update-post', $post)) { /* ... */ }

コード例で一気に見る

Gate を定義して使う(モデルに依存しない権限)
// AuthServiceProvider::boot()
Gate::define('admin-only', function ($user) {
    return $user->is_admin;
});

// コントローラ
if (Gate::allows('admin-only')) {
    // 管理者だけの処理
}

// Blade
@can('admin-only')
    <a href="/admin">管理画面</a>
@endcan
Policy でモデル単位の権限をまとめる
// php artisan make:policy PostPolicy --model=Post
class PostPolicy
{
    public function update(User $user, Post $post): bool
    {
        return $user->id === $post->user_id;
    }
}

// コントローラ: 権限なしなら 403
public function update(Post $post)
{
    $this->authorize('update', $post);
    // 自分の投稿だけ更新できる
}

いつどちらを使う?(早見表)

  • 画面でボタンやリンクを出し分けたい→ Blade の @can / @cannot(判定だけ・例外なし)
  • コントローラで「権限がなければ弾く」ようにしたい→ $this->authorize(...)(403 を投げて処理を止める)
  • 処理を分岐したい(弾かず true/false で判断)→ $user->can(...) または Gate::allows(...)
  • 1つのモデルに複数の操作権限がある→ Policy にまとめる(view/update/delete などを1クラスに)
  • モデルに紐づかない単発の権限(例: 管理者のみ)→ Gate::define(...) でゲートを1つ定義

補足: Breeze / Fortify / Sanctum / Passport の位置づけ

認証まわりには公式パッケージが複数あり、名前が似ていて混乱しがちです。 「どれが何用か」を短くまとめます。

Breeze

スターターキット

最小構成のログイン画面つきスターター

ログイン・登録・パスワードリセットなどの画面と処理を一式生成。シンプルで読みやすく、認証の仕組みを学ぶ入口に最適。中身は普通のBladeやControllerなので改造しやすい。

Fortify

認証バックエンド

画面を持たない認証バックエンド(ロジックのみ)

ログインや2段階認証などの「処理側」だけを提供し、画面は自分で用意する前提。SPAや独自デザインで認証ロジックだけ借りたいときに使う。Breeze/Jetstream の裏側でも動いている。

Sanctum

API認証

SPA・モバイル・シンプルなAPIトークン認証

同一ドメインのSPAはCookieセッションで、外部アプリには軽量なAPIトークンで認証。多くのAPIにはこれで十分。OAuthのような重い仕組みは不要なときの第一候補。

Passport

API認証

本格的なOAuth2サーバー

第三者アプリに権限を委譲するOAuth2をフル実装。アクセストークン発行やスコープ管理が必要な大規模・外部連携向け。要件が重いぶん、まずは Sanctum で足りないか検討する。

リクエスト全体の流れはリクエストライフサイクル、部品の位置関係は全体マップも参考になります。