Skip to content

認証

はじめに

多くのWebアプリケーションは、ユーザーがアプリケーションに認証し、「ログイン」する方法を提供しています。Webアプリケーションでこの機能を実装することは、複雑で潜在的にリスクのある作業になる可能性があります。そのため、Laravelは、認証を迅速かつ安全かつ簡単に実装するために必要なツールを提供することを目指しています。

Laravelの認証機能の中核は、「ガード」と「プロバイダ」で構成されています。ガードは、各リクエストに対してユーザーがどのように認証されるかを定義します。例えば、Laravelにはセッションストレージとクッキーを使用して状態を維持するsessionガードが付属しています。

プロバイダは、ユーザーが永続的なストレージからどのように取得されるかを定義します。Laravelには、Eloquentとデータベースクエリビルダを使用してユーザーを取得するためのサポートが付属しています。ただし、アプリケーションに必要に応じて追加のプロバイダを自由に定義できます。

アプリケーションの認証設定ファイルは、config/auth.phpにあります。このファイルには、Laravelの認証サービスの動作を微調整するためのいくつかのよく文書化されたオプションが含まれています。

Note

ガードとプロバイダは、「ロール」と「権限」と混同しないでください。権限を介してユーザーアクションを承認する方法の詳細については、承認のドキュメントを参照してください。

スターターキット

すぐに始めたいですか?新しいLaravelアプリケーションにLaravelアプリケーションスターターキットについてをインストールしてください。データベースをマイグレーションした後、ブラウザで/registerまたはアプリケーションに割り当てられた他のURLに移動してください。スターターキットは、認証システム全体のスキャフォールディングを行います!

最終的なLaravelアプリケーションでスターターキットを使用しない場合でも、Laravel Breezeスターターキットをインストールすることは、Laravelの認証機能を実際のLaravelプロジェクトでどのように実装するかを学ぶための素晴らしい機会です。 Laravel Breezeは認証コントローラ、ルート、ビューを作成するため、これらのファイル内のコードを調べて、Laravelの認証機能がどのように実装されるかを学ぶことができます。

データベースの考慮事項

デフォルトで、Laravelにはapp/ModelsディレクトリにApp\Models\User Eloquentモデルが含まれています。このモデルは、デフォルトのEloquent認証ドライバと共に使用できます。アプリケーションがEloquentを使用していない場合は、Laravelクエリビルダを使用するdatabase認証プロバイダを使用できます。

App\Models\Userモデルのデータベーススキーマを構築する際に、パスワード列の長さが少なくとも60文字であることを確認してください。もちろん、新しいLaravelアプリケーションに含まれるusersテーブルのマイグレーションは、この長さを超える列を既に作成しています。

また、users(または同等の)テーブルに、null許容の100文字のremember_token列が含まれていることを確認してください。この列は、アプリケーションにログインする際に「ログイン状態を維持」オプションを選択したユーザーのトークンを保存するために使用されます。繰り返しになりますが、新しいLaravelアプリケーションに含まれるデフォルトのusersテーブルのマイグレーションには、この列が既に含まれています。

エコシステムの概要

Laravelは、認証に関連するいくつかのパッケージを提供しています。続行する前に、Laravelの認証エコシステムの概要と各パッケージの目的について説明します。

まず、認証がどのように機能するかを考えてみましょう。Webブラウザを使用する場合、ユーザーはログインフォームを介してユーザー名とパスワードを提供します。これらの資格情報が正しい場合、アプリケーションは認証済みユーザーに関する情報をユーザーのセッションに保存します。ブラウザに発行されるクッキーにはセッションIDが含まれており、後続のアプリケーションへのリクエストでユーザーを正しいセッションに関連付けることができます。セッションクッキーを受け取った後、アプリケーションはセッションIDに基づいてセッションデータを取得し、認証情報がセッションに保存されていることを確認し、ユーザーを「認証済み」と見なします。

リモートサービスがAPIにアクセスするために認証する必要がある場合、通常、認証にクッキーは使用されません。代わりに、リモートサービスは各リクエストでAPIトークンをAPIに送信します。アプリケーションは、有効なAPIトークンのテーブルに対して受信トークンを検証し、そのAPIトークンに関連付けられたユーザーによってリクエストが実行されたと「認証」します。

Laravelの組み込みブラウザ認証サービスの概要

Laravelには、AuthSessionファサードを介してアクセスできる組み込みの認証およびセッションサービスが含まれています。これらの機能は、Webブラウザから開始されるリクエストに対してクッキーベースの認証を提供します。これらは、ユーザーの資格情報を検証し、ユーザーを認証するためのメソッドを提供します。さらに、これらのサービスはユーザーのセッションに適切な認証データを自動的に保存し、ユーザーのセッションクッキーを発行します。これらのサービスの使用方法についての説明は、このドキュメントに含まれています。

アプリケーションスターターキットについて

このドキュメントで説明されているように、これらの認証サービスを手動で操作して、アプリケーションの独自の認証レイヤーを構築することができます。ただし、より迅速に開始するために、無料のパッケージをリリースしています。これらのパッケージは、認証レイヤー全体の堅牢な、現代的なスキャフォールディングを提供します。これらのパッケージは、Laravel BreezeLaravel Jetstream、およびLaravel Fortifyです。

_Laravel Breeze_は、ログイン、登録、パスワードリセット、メール確認、パスワード確認など、Laravelのすべての認証機能のシンプルで最小限の実装です。Laravel Breezeのビューレイヤーは、Bladeテンプレートで構成され、Tailwind CSSでスタイリングされています。開始するには、Laravelのアプリケーションスターターキットについてのドキュメントを確認してください。

_Laravel Fortify_は、Laravelのヘッドレス認証バックエンドで、クッキーベースの認証や2要素認証、メール確認など、このドキュメントに記載されている多くの機能を実装しています。FortifyはLaravel Jetstreamの認証バックエンドを提供するか、Laravel Sanctumと組み合わせて使用することで、Laravelで認証する必要があるSPAの認証バックエンドを提供できます。

_Laravel Jetstream_は、Tailwind CSSLivewire、および/またはInertiaによって強化された美しい、現代的なUIを備えた堅牢なアプリケーションスターターキットについてで、Laravel Fortifyの認証サービスを消費および公開します。Laravel Jetstreamには、2要素認証、チームサポート、ブラウザセッション管理、プロフィール管理、およびLaravel Sanctumとの組み込み統合を含むAPIトークン認証のオプションサポートが含まれています。LaravelのAPI認証オファリングについては、以下で説明します。

LaravelのAPI認証サービスの概要

Laravelは、APIトークンの管理とAPIトークンを使用したリクエストの認証を支援するための2つのオプションパッケージを提供しています:PassportSanctumです。これらのライブラリとLaravelの組み込みのクッキーベースの認証ライブラリは相互に排他的ではないことに注意してください。これらのライブラリは主にAPIトークン認証に焦点を当てており、組み込みの認証サービスはクッキーベースのブラウザ認証に焦点を当てています。多くのアプリケーションは、Laravelの組み込みのクッキーベースの認証サービスとLaravelのAPI認証パッケージの両方を使用します。

Passport

PassportはOAuth2認証プロバイダであり、さまざまな種類のトークンを発行できるようにするさまざまなOAuth2の「付与タイプ」を提供します。一般的に、これはAPI認証のための堅牢で複雑なパッケージです。しかし、ほとんどのアプリケーションはOAuth2仕様が提供する複雑な機能を必要とせず、ユーザーや開発者の両方にとって混乱を招く可能性があります。さらに、開発者はこれまで、PassportのようなOAuth2認証プロバイダを使用してSPAアプリケーションやモバイルアプリケーションを認証する方法について混乱してきました。

Sanctum

OAuth2の複雑さと開発者の混乱に対応して、よりシンプルで合理化された認証パッケージを構築し、ウェブブラウザからのファーストパーティのウェブリクエストとトークンを介したAPIリクエストの両方を処理できるようにすることを目指しました。この目標は、Laravel Sanctumのリリースによって実現されました。これは、ファーストパーティのウェブUIとAPIを提供するアプリケーション、またはバックエンドのLaravelアプリケーションとは別に存在するシングルページアプリケーション(SPA)によって駆動されるアプリケーション、またはモバイルクライアントを提供するアプリケーションにとって、推奨される認証パッケージと考えるべきです。

Laravel Sanctumは、ウェブ/API認証のハイブリッドパッケージであり、アプリケーションの認証プロセス全体を管理できます。これが可能なのは、Sanctumベースのアプリケーションがリクエストを受け取ると、Sanctumはまず、認証されたセッションを参照するセッションクッキーがリクエストに含まれているかどうかを判断するためです。Sanctumは、以前に説明したLaravelの組み込み認証サービスを呼び出すことでこれを実現します。セッションクッキーを介してリクエストが認証されていない場合、SanctumはリクエストにAPIトークンが含まれているかどうかを検査します。APIトークンが存在する場合、Sanctumはそのトークンを使用してリクエストを認証します。このプロセスの詳細については、Sanctumの"how it works"ドキュメントを参照してください。

Laravel Sanctumは、Laravel Jetstreamアプリケーションスターターキットについてに含めるAPIパッケージとして選択されました。これは、ほとんどのウェブアプリケーションの認証ニーズに最適であると考えているためです。

認証スタックの選択ガイド

まとめると、アプリケーションがブラウザを介してアクセスされ、モノリシックなLaravelアプリケーションを構築している場合、アプリケーションはLaravelの組み込み認証サービスを使用します。

次に、アプリケーションがサードパーティによって消費されるAPIを提供する場合、アプリケーションのAPIトークン認証を提供するためにPassportまたはSanctumのいずれかを選択します。一般的に、可能な限りSanctumを優先するべきです。これは、API認証、SPA認証、モバイル認証のためのシンプルで完全なソリューションであり、「スコープ」や「能力」のサポートも含まれています。

Laravelバックエンドによって駆動されるシングルページアプリケーション(SPA)を構築している場合、Laravel Sanctumを使用するべきです。Sanctumを使用する場合、バックエンド認証ルートを手動で実装するか、Laravel Fortifyを使用して、登録、パスワードリセット、メール確認などの機能のためのルートとコントローラを提供するヘッドレス認証バックエンドサービスとして利用する必要があります。

アプリケーションがOAuth2仕様が提供するすべての機能を絶対に必要とする場合、Passportを選択することができます。

そして、迅速に開始したい場合、Laravel Breezeをお勧めします。これは、Laravelの組み込み認証サービスとLaravel Sanctumを使用した新しいLaravelアプリケーションをすぐに開始するための簡単な方法です。

認証のクイックスタート

Warning

この部分のドキュメントでは、Laravelアプリケーションスターターキットについてを介してユーザーを認証する方法について説明します。これには、迅速に開始できるようにUIのスキャフォールディングが含まれています。Laravelの認証システムと直接統合したい場合は、ユーザーの手動認証に関するドキュメントを確認してください。

スターターキットのインストール

まず、Laravelアプリケーションスターターキットについてをインストールする必要があります。現在のスターターキットであるLaravel BreezeとLaravel Jetstreamは、新しいLaravelアプリケーションに認証を組み込むための美しくデザインされた出発点を提供します。

Laravel Breezeは、ログイン、登録、パスワードリセット、メール確認、パスワード確認を含む、Laravelのすべての認証機能の最小限のシンプルな実装です。Laravel Breezeのビューレイヤーは、Tailwind CSSでスタイルされたシンプルなBladeテンプレートで構成されています。さらに、BreezeはLivewireまたはInertiaに基づくスキャフォールディングオプションを提供し、InertiaベースのスキャフォールディングにはVueまたはReactを使用する選択肢があります。

Laravel Jetstreamは、より堅牢なアプリケーションスターターキットについてであり、LivewireまたはInertiaとVueを使用してアプリケーションのスキャフォールディングをサポートします。さらに、Jetstreamは、二要素認証、チーム、プロフィール管理、ブラウザセッション管理、Laravel Sanctumを介したAPIサポート、アカウント削除などのオプション機能を備えています。

認証済みユーザーの取得

認証スターターキットをインストールし、ユーザーがアプリケーションに登録して認証できるようにした後、現在認証されているユーザーとやり取りする必要があることがよくあります。受信リクエストを処理する際、Authファサードのuserメソッドを介して認証済みユーザーにアクセスできます:

use Illuminate\Support\Facades\Auth;

// 現在認証されているユーザーを取得...
$user = Auth::user();

// 現在認証されているユーザーのIDを取得...
$id = Auth::id();

または、ユーザーが認証されると、Illuminate\Http\Requestインスタンスを介して認証済みユーザーにアクセスできます。型付きのクラスは自動的にコントローラメソッドに注入されることを覚えておいてください。Illuminate\Http\Requestオブジェクトを型付けすることで、リクエストのuserメソッドを介してアプリケーション内の任意のコントローラメソッドから認証済みユーザーに便利にアクセスできます:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;

class FlightController extends Controller
{
    /**
     * 既存のフライトのフライト情報を更新します。
     */
    public function update(Request $request): RedirectResponse
    {
        $user = $request->user();

        // ...

        return redirect('/flights');
    }
}

現在のユーザーが認証されているかどうかの確認

受信HTTPリクエストを行っているユーザーが認証されているかどうかを判断するには、Authファサードのcheckメソッドを使用できます。このメソッドは、ユーザーが認証されている場合にtrueを返します:

use Illuminate\Support\Facades\Auth;

if (Auth::check()) {
    // ユーザーはログインしています...
}

Note

checkメソッドを使用してユーザーが認証されているかどうかを判断することは可能ですが、通常はユーザーが特定のルート/コントローラにアクセスする前に認証されていることを確認するためにミドルウェアを使用します。これについて詳しくは、ルートの保護に関するドキュメントを確認してください。

ルートの保護

ルートミドルウェアを使用して、認証済みユーザーのみが特定のルートにアクセスできるようにすることができます。Laravelにはauthミドルウェアが付属しており、これはIlluminate\Auth\Middleware\Authenticateクラスのミドルウェアエイリアスです。このミドルウェアはLaravelによって内部的にエイリアスされているため、ミドルウェアをルート定義にアタッチするだけで済みます:

Route::get('/flights', function () {
    // 認証済みユーザーのみがこのルートにアクセスできます...
})->middleware('auth');

認証されていないユーザーのリダイレクト

authミドルウェアが認証されていないユーザーを検出すると、ユーザーをlogin名前付きルートにリダイレクトします。この動作は、アプリケーションのbootstrap/app.phpファイルのredirectGuestsToメソッドを使用して変更できます:

use Illuminate\Http\Request;

->withMiddleware(function (Middleware $middleware) {
    $middleware->redirectGuestsTo('/login');

    // クロージャを使用する場合...
    $middleware->redirectGuestsTo(fn (Request $request) => route('login'));
})

ガードの指定

authミドルウェアをルートにアタッチする際、ユーザーを認証するために使用する「ガード」を指定することもできます。指定されたガードは、auth.php設定ファイルのguards配列のキーのいずれかに対応する必要があります:

Route::get('/flights', function () {
    // 認証済みユーザーのみがこのルートにアクセスできます...
})->middleware('auth:admin');

ログインのスロットリング

Laravel BreezeやLaravel Jetstreamのスターターキットを使用している場合、ログイン試行に対してレート制限が自動的に適用されます。デフォルトでは、ユーザーが何度か正しい認証情報を提供できなかった場合、1分間ログインできなくなります。スロットリングはユーザーのユーザー名/メールアドレスとIPアドレスに固有です。

Note

アプリケーション内の他のルートにレート制限を適用したい場合は、レート制限のドキュメントを確認してください。

ユーザーの手動認証

Laravelのアプリケーションスターターキットについてに含まれる認証スカフォールディングを使用する必要はありません。このスカフォールディングを使用しないことを選択した場合、Laravelの認証クラスを直接使用してユーザー認証を管理する必要があります。心配はいりません、簡単です!

Laravelの認証サービスには、Auth ファサードを介してアクセスしますので、クラスの先頭でAuthファサードをインポートする必要があります。次に、attemptメソッドを見てみましょう。attemptメソッドは通常、アプリケーションの「ログイン」フォームからの認証試行を処理するために使用されます。認証が成功した場合、セッションを再生成してセッション固定攻撃を防ぐ必要があります:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Auth;

class LoginController extends Controller
{
    /**
     * 認証試行を処理します。
     */
    public function authenticate(Request $request): RedirectResponse
    {
        $credentials = $request->validate([
            'email' => ['required', 'email'],
            'password' => ['required'],
        ]);

        if (Auth::attempt($credentials)) {
            $request->session()->regenerate();

            return redirect()->intended('dashboard');
        }

        return back()->withErrors([
            'email' => '提供された認証情報が記録と一致しません。',
        ])->onlyInput('email');
    }
}

attemptメソッドは、キー/値ペアの配列を最初の引数として受け取ります。配列内の値は、データベーステーブル内のユーザーを見つけるために使用されます。したがって、上記の例では、email列の値でユーザーが取得されます。ユーザーが見つかった場合、データベースに保存されたハッシュ化されたパスワードは、配列を介してメソッドに渡されたpassword値と比較されます。受信リクエストのpassword値をハッシュ化する必要はありません。フレームワークは、データベース内のハッシュ化されたパスワードと比較する前に、値を自動的にハッシュ化します。2つのハッシュ化されたパスワードが一致する場合、ユーザーの認証済みセッションが開始されます。

Laravelの認証サービスは、認証ガードの「プロバイダ」設定に基づいてデータベースからユーザーを取得します。デフォルトのconfig/auth.php設定ファイルでは、Eloquentユーザープロバイダが指定されており、ユーザーを取得する際にApp\Models\Userモデルを使用するように指示されています。アプリケーションのニーズに基づいて、設定ファイル内でこれらの値を変更できます。

attemptメソッドは、認証が成功した場合はtrueを、失敗した場合はfalseを返します。

Laravelのリダイレクタが提供するintendedメソッドは、認証ミドルウェアによってインターセプトされる前にユーザーがアクセスしようとしていたURLにユーザーをリダイレクトします。意図された宛先が利用できない場合、このメソッドにフォールバックURIを指定できます。

追加の条件の指定

必要に応じて、ユーザーのメールとパスワードに加えて、認証クエリに追加のクエリ条件を追加することもできます。これを行うには、attemptメソッドに渡される配列にクエリ条件を単純に追加します。たとえば、ユーザーが「アクティブ」とマークされていることを確認できます:

if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) {
    // 認証が成功しました...
}

複雑なクエリ条件の場合、認証情報の配列にクロージャを提供できます。このクロージャはクエリインスタンスで呼び出され、アプリケーションのニーズに基づいてクエリをカスタマイズできます:

use Illuminate\Database\Eloquent\Builder;

if (Auth::attempt([
    'email' => $email,
    'password' => $password,
    fn (Builder $query) => $query->has('activeSubscription'),
])) {
    // 認証が成功しました...
}

Warning

これらの例では、emailは必須オプションではありません。単に例として使用されています。データベーステーブルの「ユーザー名」に対応する列名を使用する必要があります。

attemptWhenメソッドは、2番目の引数としてクロージャを受け取り、実際にユーザーを認証する前に潜在的なユーザーをより徹底的に検査するために使用できます。クロージャは潜在的なユーザーを受け取り、ユーザーが認証されるかどうかを示すためにtrueまたはfalseを返す必要があります:

if (Auth::attemptWhen([
    'email' => $email,
    'password' => $password,
], function (User $user) {
    return $user->isNotBanned();
})) {
    // 認証が成功しました...
}

特定のガードインスタンスへのアクセス

Authファサードのguardメソッドを介して、ユーザーを認証する際に使用するガードインスタンスを指定できます。これにより、完全に別々の認証可能なモデルまたはユーザーテーブルを使用して、アプリケーションの別々の部分の認証を管理できます。

guardメソッドに渡されるガード名は、auth.php設定ファイルで設定されたガードのいずれかに対応する必要があります:

if (Auth::guard('admin')->attempt($credentials)) {
    // ...
}

ユーザーの記憶

多くのWebアプリケーションは、ログインフォームに「記憶する」チェックボックスを提供しています。アプリケーションで「記憶する」機能を提供したい場合、attemptメソッドにブール値を2番目の引数として渡すことができます。

この値がtrueの場合、Laravelはユーザーを無期限に認証したままにするか、手動でログアウトするまで認証したままにします。usersテーブルには、「記憶する」トークンを保存するために使用される文字列のremember_token列が含まれている必要があります。新しいLaravelアプリケーションに含まれるusersテーブルマイグレーションには、すでにこの列が含まれています:

use Illuminate\Support\Facades\Auth;

if (Auth::attempt(['email' => $email, 'password' => $password], $remember)) {
    // ユーザーは記憶されています...
}

アプリケーションが「ログイン状態を維持する」機能を提供している場合、viaRememberメソッドを使用して、現在認証されているユーザーが「記憶する」クッキーを使用して認証されたかどうかを判断できます:

use Illuminate\Support\Facades\Auth;

if (Auth::viaRemember()) {
    // ...
}

その他の認証方法

ユーザーインスタンスの認証

既存の既存のユーザーインスタンスを現在認証されているユーザーとして設定したい場合、ユーザーインスタンスをAuthファサードのloginメソッドに渡すことができます。指定されたユーザーインスタンスは、Illuminate\Contracts\Auth\Authenticatable 契約の実装である必要があります。Laravelに含まれるApp\Models\Userモデルは、すでにこのインターフェースを実装しています。この認証方法は、ユーザーがアプリケーションに登録した直後など、既に有効なユーザーインスタンスが存在する場合に便利です:

use Illuminate\Support\Facades\Auth;

Auth::login($user);

loginメソッドにブール値を2番目の引数として渡すことができます。この値は、認証されたセッションに「記憶する」機能が必要かどうかを示します。これは、セッションが無期限に認証されたままになるか、ユーザーが手動でアプリケーションからログアウトするまで認証されたままになることを意味します:

Auth::login($user, $remember = true);

必要に応じて、loginメソッドを呼び出す前に認証ガードを指定できます:

Auth::guard('admin')->login($user);

IDによるユーザーの認証

データベースレコードの主キーを使用してユーザーを認証するには、loginUsingIdメソッドを使用できます。このメソッドは、認証したいユーザーの主キーを受け取ります:

Auth::loginUsingId(1);

loginUsingIdメソッドのremember引数にブール値を渡すことができます。この値は、認証されたセッションに「記憶する」機能が必要かどうかを示します。これは、セッションが無期限に認証されたままになるか、ユーザーが手動でアプリケーションからログアウトするまで認証されたままになることを意味します:

Auth::loginUsingId(1, remember: true);

ユーザーの一時的な認証

onceメソッドを使用して、ユーザーをアプリケーションに対して単一のリクエストで認証することができます。このメソッドを呼び出す際にセッションやクッキーは使用されません:

if (Auth::once($credentials)) {
    // ...
}

HTTP基本認証

HTTP基本認証は、専用の「ログイン」ページを設定せずにアプリケーションのユーザーを認証するための迅速な方法を提供します。これを開始するには、auth.basic ミドルウェアをルートにアタッチします。auth.basicミドルウェアはLaravelフレームワークに含まれているため、定義する必要はありません:

Route::get('/profile', function () {
    // 認証されたユーザーのみがこのルートにアクセスできます...
})->middleware('auth.basic');

ミドルウェアがこのミドルウェアがルートにアタッチされると、ブラウザでそのルートにアクセスする際に自動的に認証情報の入力が求められます。デフォルトでは、auth.basicミドルウェアは、usersデータベーステーブルのemailカラムをユーザーの「ユーザー名」とみなします。

FastCGIに関する注意

LaravelアプリケーションをPHP FastCGIとApacheで提供している場合、HTTP Basic認証が正しく機能しない可能性があります。これらの問題を修正するには、アプリケーションの.htaccessファイルに以下の行を追加してください。

RewriteCond %{HTTP:Authorization} ^(.+)$
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

ステートレスなHTTP Basic認証

セッションにユーザー識別子のクッキーを設定せずに、ステートレスなHTTP Basic認証を使用することもできます。これは主に、アプリケーションのAPIへのリクエストを認証するためにHTTP認証を使用する場合に便利です。これを実現するには、onceBasicメソッドを呼び出すミドルウェアを定義します。onceBasicメソッドがレスポンスを返さない場合、リクエストはアプリケーションにさらに渡されます。

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;

class AuthenticateOnceWithBasicAuth
{
    /**
     * 受信リクエストの処理
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        return Auth::onceBasic() ?: $next($request);
    }

}

次に、ミドルウェアをルートにアタッチします。

Route::get('/api/user', function () {
    // 認証されたユーザーのみがこのルートにアクセスできます...
})->middleware(AuthenticateOnceWithBasicAuth::class);

ログアウト

アプリケーションから手動でユーザーをログアウトさせるには、Authファサードが提供するlogoutメソッドを使用できます。これにより、ユーザーのセッションから認証情報が削除され、後続のリクエストが認証されなくなります。

logoutメソッドを呼び出すだけでなく、ユーザーのセッションを無効にし、CSRFトークンを再生成することを推奨します。ユーザーをログアウトした後、通常はアプリケーションのルートにユーザーをリダイレクトします。

use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Auth;

/**
 * アプリケーションからユーザーをログアウトさせる
 */
public function logout(Request $request): RedirectResponse
{
    Auth::logout();

    $request->session()->invalidate();

    $request->session()->regenerateToken();

    return redirect('/');
}

他のデバイスでのセッションの無効化

Laravelは、ユーザーの現在のデバイスのセッションを維持したまま、他のデバイスでアクティブなセッションを無効化して「ログアウト」させるメカニズムも提供しています。この機能は、通常、ユーザーがパスワードを変更または更新した際に、他のデバイスのセッションを無効化したいが、現在のデバイスは認証されたままにしたい場合に利用されます。

開始する前に、Illuminate\Session\Middleware\AuthenticateSessionミドルウェアがセッション認証を受けるルートに含まれていることを確認する必要があります。通常、このミドルウェアをルートグループの定義に配置して、アプリケーションの大部分のルートに適用できるようにします。デフォルトでは、AuthenticateSessionミドルウェアはauth.sessionミドルウェアエイリアスを使用してルートにアタッチできます。

Route::middleware(['auth', 'auth.session'])->group(function () {
    Route::get('/', function () {
        // ...
    });
});

次に、Authファサードが提供するlogoutOtherDevicesメソッドを使用できます。このメソッドは、ユーザーが現在のパスワードを確認する必要があり、アプリケーションは入力フォームを介してこのパスワードを受け入れる必要があります。

use Illuminate\Support\Facades\Auth;

Auth::logoutOtherDevices($currentPassword);

logoutOtherDevicesメソッドが呼び出されると、ユーザーの他のセッションは完全に無効化され、以前に認証されていたすべてのガードから「ログアウト」されます。

パスワード確認機能

アプリケーションを構築する際、ユーザーがアクションを実行する前、またはユーザーがアプリケーションの機密性の高い領域にリダイレクトされる前に、パスワード確認機能を求めるアクションがあるかもしれません。Laravelには、このプロセスを簡単にするための組み込みミドルウェアが含まれています。この機能を実装するには、2つのルートを定義する必要があります。1つはユーザーにパスワード確認機能を求めるビューを表示するルート、もう1つはパスワードが有効であることを確認し、ユーザーを目的の宛先にリダイレクトするルートです。

Note

以下のドキュメントでは、Laravelのパスワード確認機能と直接統合する方法について説明します。ただし、より迅速に開始したい場合は、Laravelアプリケーションスターターキットについてにはこの機能が含まれています。

設定

パスワードを確認した後、ユーザーは3時間以内に再度パスワード確認機能を求められることはありません。ただし、アプリケーションのconfig/auth.php設定ファイル内のpassword_timeout設定値を変更することで、ユーザーが再度パスワード確認機能を求められるまでの時間を設定できます。

ルーティング

パスワード確認フォーム

まず、ユーザーにパスワード確認機能を求めるビューを表示するルートを定義します。

Route::get('/confirm-password', function () {
    return view('auth.confirm-password');
})->middleware('auth')->name('password.confirm');

予想されるように、このルートによって返されるビューにはpasswordフィールドを含むフォームが必要です。さらに、ユーザーがアプリケーションの保護された領域に入力しており、パスワード確認機能が必要であることを説明するテキストをビューに含めることもできます。

パスワード確認機能

次に、「パスワード確認」ビューからのフォームリクエストを処理するルートを定義します。このルートは、パスワードを検証し、ユーザーを目的の宛先にリダイレクトする役割を果たします。

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Redirect;

Route::post('/confirm-password', function (Request $request) {
    if (! Hash::check($request->password, $request->user()->password)) {
        return back()->withErrors([
            'password' => ['提供されたパスワードが記録と一致しません。']
        ]);
    }

    $request->session()->passwordConfirmed();

    return redirect()->intended();
})->middleware(['auth', 'throttle:6,1']);

このルートについて詳しく見てみましょう。まず、リクエストのpasswordフィールドが認証されたユーザーのパスワードと実際に一致するかどうかを確認します。パスワードが有効な場合、Laravelのセッションにユーザーがパスワードを確認したことを通知する必要があります。passwordConfirmedメソッドは、ユーザーが最後にパスワードを確認した時刻を示すタイムスタンプをユーザーのセッションに設定します。最後に、ユーザーを目的の宛先にリダイレクトできます。

ルートの保護

最近のパスワード確認を必要とするアクションを実行するルートには、password.confirmミドルウェアを割り当てる必要があります。このミドルウェアはLaravelのデフォルトインストールに含まれており、ユーザーの目的の宛先をセッションに自動的に保存するため、ユーザーはパスワードを確認した後にその場所にリダイレクトされます。セッションにユーザーの目的の宛先を保存した後、ミドルウェアはユーザーをpassword.confirm名前付きルートにリダイレクトします。

Route::get('/settings', function () {
    // ...
})->middleware(['password.confirm']);

Route::post('/settings', function () {
    // ...
})->middleware(['password.confirm']);

カスタムガードの追加

Authファサードのextendメソッドを使用して独自の認証ガードを定義できます。サービスプロバイダ内でextendメソッドの呼び出しを配置する必要があります。LaravelにはすでにAppServiceProviderが付属しているため、そのプロバイダにコードを配置できます。

<?php

namespace App\Providers;

use App\Services\Auth\JwtGuard;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    // ...

    /**
     * 任意のアプリケーションサービスのブートストラップ
     */
    public function boot(): void
    {
        Auth::extend('jwt', function (Application $app, string $name, array $config) {
            // Illuminate\Contracts\Auth\Guardのインスタンスを返す...

            return new JwtGuard(Auth::createUserProvider($config['provider']));
        });
    }
}

上記の例でわかるように、extendメソッドに渡されるコールバックは、Illuminate\Contracts\Auth\Guardの実装を返す必要があります。このインターフェースには、カスタムガードを定義するために実装する必要があるいくつかのメソッドが含まれています。カスタムガードを定義したら、auth.php設定ファイルのguards設定でそのガードを参照できます。

'guards' => [
    'api' => [
        'driver' => 'jwt',
        'provider' => 'users',
    ],
],

クロージャリクエストガード

カスタムのHTTPリクエストベースの認証システムを実装する最も簡単な方法は、Auth::viaRequestメソッドを使用することです。このメソッドを使用すると、単一のクロージャを使用して認証プロセスを迅速に定義できます。

始めるには、アプリケーションのAppServiceProviderbootメソッド内でAuth::viaRequestメソッドを呼び出します。viaRequestメソッドは、認証ドライバ名を最初の引数として受け取ります。この名前は、カスタムガードを説明する任意の文字列にすることができます。メソッドに渡される2番目の引数は、受信したHTTPリクエストを受け取り、認証が成功した場合はユーザーインスタンスを、失敗した場合はnullを返すクロージャである必要があります。

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

/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    Auth::viaRequest('custom-token', function (Request $request) {
        return User::where('token', (string) $request->token)->first();
    });
}

カスタム認証ドライバを定義したら、auth.php設定ファイルのguards設定内でドライバとして設定できます。

'guards' => [
    'api' => [
        'driver' => 'custom-token',
    ],
],

最後に、認証ミドルウェアをルートに割り当てる際にガードを参照できます。

Route::middleware('auth:api')->group(function () {
    // ...
});

カスタムユーザープロバイダの追加

ユーザーを保存するために従来のリレーショナルデータベースを使用していない場合は、Laravelを独自の認証ユーザープロバイダで拡張する必要があります。Authファサードのproviderメソッドを使用して、カスタムユーザープロバイダを定義します。ユーザープロバイダリゾルバは、Illuminate\Contracts\Auth\UserProviderの実装を返す必要があります。

<?php

namespace App\Providers;

use App\Extensions\MongoUserProvider;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    // ...

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        Auth::provider('mongo', function (Application $app, array $config) {
            // Return an instance of Illuminate\Contracts\Auth\UserProvider...

            return new MongoUserProvider($app->make('mongo.connection'));
        });
    }
}

providerメソッドを使用してプロバイダを登録した後、auth.php設定ファイルで新しいユーザープロバイダに切り替えることができます。まず、新しいドライバを使用するプロバイダを定義します。

'providers' => [
    'users' => [
        'driver' => 'mongo',
    ],
],

最後に、このプロバイダをguards設定で参照できます。

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

ユーザープロバイダ契約

Illuminate\Contracts\Auth\UserProviderの実装は、MySQL、MongoDBなどの永続ストレージシステムからIlluminate\Contracts\Auth\Authenticatableの実装を取得する責任があります。これらの2つのインターフェースにより、ユーザーデータがどのように保存されているか、または認証されたユーザーを表すためにどのようなクラスが使用されているかに関係なく、Laravelの認証メカニズムが機能し続けることができます。

Illuminate\Contracts\Auth\UserProvider契約を見てみましょう。

<?php

namespace Illuminate\Contracts\Auth;

interface UserProvider
{
    public function retrieveById($identifier);
    public function retrieveByToken($identifier, $token);
    public function updateRememberToken(Authenticatable $user, $token);
    public function retrieveByCredentials(array $credentials);
    public function validateCredentials(Authenticatable $user, array $credentials);
    public function rehashPasswordIfRequired(Authenticatable $user, array $credentials, bool $force = false);
}

retrieveById関数は通常、MySQLデータベースからの自動増分IDなど、ユーザーを表すキーを受け取ります。IDに一致するAuthenticatableの実装がメソッドによって取得され、返される必要があります。

retrieveByToken関数は、ユーザーの一意の$identifierと「remember me」$tokenによってユーザーを取得します。通常、これはremember_tokenというデータベース列に保存されます。前のメソッドと同様に、トークン値が一致するAuthenticatableの実装がこのメソッドによって返される必要があります。

updateRememberTokenメソッドは、$userインスタンスのremember_tokenを新しい$tokenで更新します。新しいトークンは、ユーザーが「remember me」認証の試みに成功したとき、またはユーザーがログアウトしたときに割り当てられます。

retrieveByCredentialsメソッドは、アプリケーションに認証を試みるときにAuth::attemptメソッドに渡される資格情報の配列を受け取ります。このメソッドは、その資格情報に一致するユーザーを基礎となる永続ストレージに「クエリ」する必要があります。通常、このメソッドは、$credentials['username']の値に一致する「username」を持つユーザーレコードを検索する「where」条件を持つクエリを実行します。このメソッドは、Authenticatableの実装を返す必要があります。このメソッドは、パスワードの検証や認証を試みるべきではありません。

validateCredentialsメソッドは、指定された$user$credentialsと比較してユーザーを認証する必要があります。例えば、このメソッドは通常、Hash::checkメソッドを使用して、$user->getAuthPassword()の値を$credentials['password']の値と比較します。このメソッドは、パスワードが有効かどうかを示すtrueまたはfalseを返す必要があります。

rehashPasswordIfRequiredメソッドは、必要であれば指定された$userのパスワードを再ハッシュする必要があります。例えば、このメソッドは通常、Hash::needsRehashメソッドを使用して、$credentials['password']の値を再ハッシュする必要があるかどうかを判断します。パスワードを再ハッシュする必要がある場合、このメソッドはHash::makeメソッドを使用してパスワードを再ハッシュし、基礎となる永続ストレージ内のユーザーレコードを更新する必要があります。

Authenticatable契約

UserProviderの各メソッドについて調べたので、Authenticatable契約を見てみましょう。retrieveByIdretrieveByTokenretrieveByCredentialsメソッドからは、このインターフェースの実装を返す必要があります。

<?php

namespace Illuminate\Contracts\Auth;

interface Authenticatable
{
    public function getAuthIdentifierName();
    public function getAuthIdentifier();
    public function getAuthPasswordName();
    public function getAuthPassword();
    public function getRememberToken();
    public function setRememberToken($value);
    public function getRememberTokenName();
}

このインターフェースはシンプルです。getAuthIdentifierNameメソッドは、ユーザーの「主キー」列の名前を返す必要があり、getAuthIdentifierメソッドはユーザーの「主キー」を返す必要があります。MySQLバックエンドを使用する場合、これはユーザーレコードに割り当てられた自動増分主キーである可能性があります。getAuthPasswordNameメソッドは、ユーザーのパスワード列の名前を返す必要があります。getAuthPasswordメソッドは、ユーザーのハッシュ化されたパスワードを返す必要があります。

このインターフェースにより、認証システムはORMまたはストレージ抽象化レイヤーに関係なく、任意の「ユーザー」クラスで動作できます。デフォルトでは、Laravelにはapp/Modelsディレクトリにこのインターフェースを実装するApp\Models\Userクラスが含まれています。

自動パスワード再ハッシュ

Laravelのデフォルトのパスワードハッシュアルゴリズムはbcryptです。bcryptハッシュの「作業係数」は、アプリケーションのconfig/hashing.php設定ファイルまたはBCRYPT_ROUNDS環境変数を介して調整できます。

通常、bcrypt作業係数は、CPU/GPU処理能力の向上に伴い時間とともに増加する必要があります。アプリケーションのbcrypt作業係数を増やす場合、Laravelは、Laravelのスターターキットを介してユーザーがアプリケーションに認証するとき、またはattemptメソッドを介して手動でユーザーを認証するときに、ユーザーパスワードを優雅に自動的に再ハッシュします。

通常、自動パスワード再ハッシュはアプリケーションに影響を与えるべきではありませんが、この動作を無効にすることができます。hashing設定ファイルを公開することで無効にできます。

php artisan config:publish hashing

設定ファイルが公開されたら、rehash_on_login設定値をfalseに設定できます。

'rehash_on_login' => false,

イベント

Laravelは、認証プロセス中にさまざまなイベントをディスパッチします。次のイベントのいずれかにリスナーを定義することができます。

イベント名
Illuminate\Auth\Events\Registered
Illuminate\Auth\Events\Attempting
Illuminate\Auth\Events\Authenticated
Illuminate\Auth\Events\Login
Illuminate\Auth\Events\Failed
Illuminate\Auth\Events\Validated
Illuminate\Auth\Events\Verified
Illuminate\Auth\Events\Logout
Illuminate\Auth\Events\CurrentDeviceLogout
Illuminate\Auth\Events\OtherDeviceLogout
Illuminate\Auth\Events\Lockout
Illuminate\Auth\Events\PasswordReset

ユーザーノート