この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:4
ページ更新者:T
更新日時:2026-06-11 07:07:02

タイトル: ログインの必須化
SEOタイトル: Laravel 認証必須化 (auth Middleware) 完全ガイド|Web / API / Sanctum 統合

この記事の要点
  • Laravel で「ログインしないと見せない」はルートに middleware('auth') を付けるのが基本。グループで複数ルートに一括適用
  • Controller 側で必須化するなら コンストラクタ$this->middleware('auth')except / only でアクション単位除外可能
  • API は Sanctum (auth:sanctum)、SPA は同じく Sanctum の Cookie 認証、Mobile は Token 認証で統一できる
  • 未認証時のリダイレクト先は app/Http/Middleware/Authenticate.phpredirectTo() で制御。API リクエストは JSON 401 を返すべき
  • スターターキット (Breeze / Jetstream) を使えば、ログイン画面・登録・パスワードリセットまで一括スキャフォールド可能

Laravel の認証システム概要

Laravel は Guard (認証方式)Provider (ユーザー取得元) を組み合わせて認証を構成します。設定は config/auth.php。デフォルトは Web Guard (Session ベース) + Eloquent User モデル。

// config/auth.php (抜粋)
'defaults' => [
    'guard' => 'web',
    'passwords' => 'users',
],

'guards' => [
    'web' => ['driver' => 'session', 'provider' => 'users'],
    'api' => ['driver' => 'token',   'provider' => 'users'],  // 旧 token
    // Sanctum 利用時は別途設定
],

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

パターン 1: ルート単位の auth Middleware

もっともシンプルで頻出するパターン。routes/web.php でルートに auth ミドルウェアを付与します。

// routes/web.php
use Illuminate\Support\Facades\Route;

// 公開ページ (ログイン不要)
Route::get('/', [HomeController::class, 'index']);
Route::get('/about', fn () => view('about'));

// ログイン必須エリア
Route::middleware('auth')->group(function () {
    Route::get('/dashboard',   [DashboardController::class, 'index']);
    Route::get('/profile',     [ProfileController::class, 'show']);
    Route::put('/profile',     [ProfileController::class, 'update']);
    Route::post('/logout',     [AuthController::class,    'logout']);
});

// 認証 + 検証済メール必須
Route::middleware(['auth', 'verified'])->group(function () {
    Route::get('/billing', [BillingController::class, 'index']);
});

// 認証 + 管理者ロールのみ
Route::middleware(['auth', 'role:admin'])->group(function () {
    Route::get('/admin', [AdminController::class, 'index']);
});

パターン 2: Controller コンストラクタで一括

1 つの Controller のほぼ全アクションがログイン必須なら、コンストラクタで指定が楽です。

namespace App\Http\Controllers;

class ArticleController extends Controller
{
    public function __construct()
    {
        // 全アクションに auth を適用
        $this->middleware('auth');

        // 例外: 一覧と詳細だけは公開
        $this->middleware('auth')->except(['index', 'show']);

        // または特定アクションのみ
        $this->middleware('auth')->only(['create', 'store', 'update', 'destroy']);
    }
}

Laravel 11+ では Controller のコンストラクタ Middleware が削除され、ルート側で指定するスタイルに統一されました。バージョンに応じて使い分け。

パターン 3: Laravel 11+ 推奨スタイル

// Laravel 11+ では HasMiddleware インターフェース
namespace App\Http\Controllers;

use Illuminate\Routing\Controllers\HasMiddleware;
use Illuminate\Routing\Controllers\Middleware;

class ArticleController extends Controller implements HasMiddleware
{
    public static function middleware(): array
    {
        return [
            'auth',                                          // 全アクション
            new Middleware('auth', except: ['index', 'show']), // 一部除外
            new Middleware(['auth', 'verified'], only: ['edit', 'update']),
        ];
    }

    public function index() { /* 公開 */ }
    public function show($id) { /* 公開 */ }
    public function edit($id) { /* 認証 + 検証済 */ }
}

主要な認証 Middleware

Middleware役割未認証時
authデフォルト Guard で認証必須login ルートへリダイレクト
auth:webweb Guard を明示同上
auth:apiapi Guard401 JSON
auth:sanctumSanctum (SPA + API + Mobile)401 JSON or リダイレクト
auth.basicHTTP Basic 認証401 + WWW-Authenticate
auth.sessionセッションがあれば認証
guest未ログイン専用 (ログイン画面など)ホームへリダイレクト
verifiedメール検証済必須verification 画面へ
password.confirm直近で再認証必須パスワード再確認画面

未認証時のリダイレクト先カスタマイズ

// Laravel 10 以前: app/Http/Middleware/Authenticate.php
namespace App\Http\Middleware;

use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Illuminate\Http\Request;

class Authenticate extends Middleware
{
    protected function redirectTo(Request $request): ?string
    {
        // API リクエストは null を返して 401 を発生させる
        if ($request->expectsJson()) {
            return null;
        }
        // ブラウザはログイン画面へ
        return route('login');
    }
}
// Laravel 11+: bootstrap/app.php
return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(...)
    ->withMiddleware(function (Middleware $middleware) {
        $middleware->redirectGuestsTo(fn () => route('login'));
        $middleware->redirectUsersTo('/dashboard');
    })
    ->create();

Blade での出し分け

@auth
    {{-- ログイン中だけ表示 --}}
    

こんにちは、{{ Auth::user()->name }} さん

@csrf
@endauth @guest {{-- 未ログイン時だけ表示 --}} ログイン 新規登録 @endguest @auth('admin') {{-- 別 Guard で判定 --}} 管理画面 @endauth

Sanctum での API 認証

SPA / モバイル / API のどれを書いていても Sanctum 1 つで網羅できるのが現代の Laravel スタンダードです。

composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
// routes/api.php
Route::middleware('auth:sanctum')->group(function () {
    Route::get('/user', fn (Request $r) => $r->user());
    Route::apiResource('articles', ArticleController::class);
});

// トークン発行 (モバイル / 外部システム)
$user = User::find(1);
$token = $user->createToken('mobile-app')->plainTextToken;
// → ヘッダ: Authorization: Bearer 1|abc...

// User モデル
class User extends Authenticatable
{
    use HasApiTokens;   // ← Sanctum 必須トレイト
}

スターターキットを使う

ログイン画面・登録画面・パスワードリセットを自分で書く必要はありません。Laravel 公式のスキャフォールドを使いましょう。

キット特徴用途
Breeze★ 最小構成 (Blade / Vue / React / API)シンプル CRUD アプリ
JetstreamTeams / 2FA / API トークン / Profile 管理SaaS
FortifyUI 無しのバックエンドのみ独自フロント / Inertia 系
# Breeze (Blade 版) の例
composer require laravel/breeze --dev
php artisan breeze:install blade
npm install && npm run dev
php artisan migrate

# /login /register /password/reset /verify-email
# ルートが自動生成 + UI 完成

パスワード再確認

支払い情報変更や退会などセンシティブな操作には、ログイン済でも再度パスワード確認を求めます。

Route::middleware(['auth', 'password.confirm'])->group(function () {
    Route::delete('/account', [AccountController::class, 'destroy']);
    Route::post('/billing/card', [BillingController::class, 'updateCard']);
});

// 確認後の有効期限 (秒) は config/auth.php
'password_timeout' => 10800,   // 既定 3 時間

API リクエストへの 401 JSON 返却

SPA / モバイルからの API リクエストは HTML へリダイレクトされても困ります。Accept: application/json ヘッダ付きなら自動で 401 JSON が返ります。

HTTP/1.1 401 Unauthorized
Content-Type: application/json

{
  "message": "Unauthenticated."
}

テスト

use App\Models\User;

it('未ログインユーザーはダッシュボードからリダイレクトされる', function () {
    $this->get('/dashboard')->assertRedirect('/login');
});

it('ログイン済ならダッシュボードが見える', function () {
    $user = User::factory()->create();
    $this->actingAs($user)
        ->get('/dashboard')
        ->assertOk();
});

it('API は 401 JSON を返す', function () {
    $this->getJson('/api/user')->assertStatus(401);
});

FAQ

Q: ログイン後に元のページに戻したい
A: auth Middleware は未認証時に url()->previous() をセッションに保存し、ログイン後 redirect()->intended('/default') で復元します。標準でこの動作が含まれているはず。

Q: 一部の URL だけログインを免除したい
A: ルートを別グループに分け、Route::middleware('auth')->group(...) の外に置きます。Controller 単位なら except 引数で指定。

Q: 複数の認証 (顧客 / 管理者) を使い分けたい
A: config/auth.php に複数 Guard と Provider を定義し、auth:admin のように Guard 名付きで Middleware 指定します。

Q: ログインしているのに毎回ログイン画面に戻される
A: セッションドライバの設定ミスが多い。SESSION_DRIVER=file なら storage/framework/sessions の権限、cookie なら SESSION_DOMAIN 設定、HTTPS なら SESSION_SECURE_COOKIE=true を確認。

Q: API でログイン状態をフロントに通知したい
A: SPA + Sanctum の Cookie 認証なら /api/user を叩いて 200 ならログイン中、401 なら未ログインと判定。CSRF は /sanctum/csrf-cookie 先取りが必要。