コンテンツへスキップ

認証

はじめに

多くのウェブアプリケーションは、ユーザーがアプリケーションで認証して「ログイン」する方法を提供しています。ウェブアプリケーションでこの機能を実装することは、複雑でリスクを伴う可能性があります。このため、Laravelは、認証を迅速、安全、かつ容易に実装するために必要なツールを提供することに努めています。

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

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

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

lightbulb

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

スターターキット

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

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

データベースに関する考慮事項

デフォルトでは、Laravelはapp/ModelsディレクトリにApp\Models\User Eloquentモデルを含んでいます。このモデルは、デフォルトのEloquent認証ドライバで使用できます。

アプリケーションがEloquentを使用していない場合は、Laravelクエリビルダーを使用するdatabase認証プロバイダを使用できます。アプリケーションがMongoDBを使用している場合は、MongoDBの公式Laravelユーザー認証ドキュメントを確認してください。

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

また、users(または同等のもの)テーブルに、100文字のNULL許容文字列remember_token列が含まれていることを確認する必要があります。この列は、アプリケーションにログインする際に「記憶する」オプションを選択したユーザーのトークンを格納するために使用されます。繰り返しますが、新しいLaravelアプリケーションに含まれるデフォルトのusersテーブルマイグレーションには、すでにこの列が含まれています。

エコシステムの概要

Laravelは、認証に関連するいくつかのパッケージを提供しています。先に進む前に、Laravelの一般的な認証エコシステムを確認し、各パッケージの目的について説明します。

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

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

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

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

アプリケーションスターターキット

このドキュメントで説明されているように、これらの認証サービスと手動でやり取りして、アプリケーション独自の認証レイヤーを構築できます。ただし、より迅速に開始するために、認証レイヤー全体の堅牢で最新の足場を提供する無料のパッケージをリリースしました。これらのパッケージは、Laravel BreezeLaravel Jetstream、およびLaravel Fortifyです。

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

Laravel FortifyはLaravel向けのヘッドレス認証バックエンドであり、このドキュメントにある多くの機能(Cookieベースの認証、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の組み込みCookieベースの認証ライブラリは、相互に排他的ではないことに注意してください。これらのライブラリは主にAPIトークン認証に焦点を当てている一方、組み込みの認証サービスはCookieベースのブラウザ認証に焦点を当てています。多くのアプリケーションでは、Laravelの組み込みCookieベースの認証サービスと、LaravelのAPI認証パッケージのいずれかを使用します。

Passport

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

Sanctum

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

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

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

概要とスタックの選択

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

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

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

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

そして、迅速に開始したい場合は、Laravelの組み込み認証サービスとLaravel Sanctumという推奨される認証スタックを既に使用している新しいLaravelアプリケーションを迅速に開始する方法として、Laravel Breezeを推奨いたします。

認証クイックスタート

exclamation

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

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

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

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

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

認証済みユーザーの取得

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

use Illuminate\Support\Facades\Auth;
 
// Retrieve the currently authenticated user...
$user = Auth::user();
 
// Retrieve the currently authenticated user's 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
{
/**
* Update the flight information for an existing flight.
*/
public function update(Request $request): RedirectResponse
{
$user = $request->user();
 
// ...
 
return redirect('/flights');
}
}

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

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

use Illuminate\Support\Facades\Auth;
 
if (Auth::check()) {
// The user is logged in...
}
lightbulb

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

ルートの保護

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

Route::get('/flights', function () {
// Only authenticated users may access this route...
})->middleware('auth');

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

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

use Illuminate\Http\Request;
 
->withMiddleware(function (Middleware $middleware) {
$middleware->redirectGuestsTo('/login');
 
// Using a closure...
$middleware->redirectGuestsTo(fn (Request $request) => route('login'));
})

ガードの指定

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

Route::get('/flights', function () {
// Only authenticated users may access this route...
})->middleware('auth:admin');

ログインスロットリング

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

lightbulb

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

ユーザーの手動認証

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

`Auth`ファサードを介してLaravelの認証サービスにアクセスするため、クラスの先頭に`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
{
/**
* Handle an authentication attempt.
*/
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' => 'The provided credentials do not match our records.',
])->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])) {
// Authentication was successful...
}

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

use Illuminate\Database\Eloquent\Builder;
 
if (Auth::attempt([
'email' => $email,
'password' => $password,
fn (Builder $query) => $query->has('activeSubscription'),
])) {
// Authentication was successful...
}
exclamation

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

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

if (Auth::attemptWhen([
'email' => $email,
'password' => $password,
], function (User $user) {
return $user->isNotBanned();
})) {
// Authentication was successful...
}

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

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

`guard`メソッドに渡されるガード名は、`auth.php`構成ファイルで構成されているガードのいずれかに対応している必要があります。

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

ユーザーの記憶

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

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

use Illuminate\Support\Facades\Auth;
 
if (Auth::attempt(['email' => $email, 'password' => $password], $remember)) {
// The user is being remembered...
}

アプリケーションで「Remember Me」機能を提供する場合は、viaRememberメソッドを使用して、現在認証されているユーザーが「Remember Me」クッキーを使用して認証されたかどうかを判断できます。

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引数としてブール値を渡すことができます。この値は、認証されたセッションで「Remember Me」機能を有効にするかどうかを示します。これは、セッションが無期限に、またはユーザーが手動でアプリケーションからログアウトするまで認証されることを意味します。

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

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

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

IDによるユーザー認証

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

Auth::loginUsingId(1);

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

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

一度限りのユーザー認証

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

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

HTTP基本認証

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

Route::get('/profile', function () {
// Only authenticated users may access this route...
})->middleware('auth.basic');

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

FastCGIに関する注意

PHP FastCGIとApacheを使用してLaravelアプリケーションを提供している場合、HTTP基本認証が正しく動作しない場合があります。これらの問題を修正するには、アプリケーションの.htaccessファイルに次の行を追加できます。

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

ステートレスHTTP基本認証

セッションにユーザー識別子クッキーを設定せずにHTTP基本認証を使用することもできます。これは、アプリケーションの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
{
/**
* Handle an incoming request.
*
* @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 () {
// Only authenticated users may access this route...
})->middleware(AuthenticateOnceWithBasicAuth::class);

ログアウト

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

logoutメソッドを呼び出すことに加えて、ユーザーのセッションを無効にし、CSRFトークンを再生成することをお勧めします。ユーザーをログアウトした後、通常はユーザーをアプリケーションのルートにリダイレクトします。

use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Auth;
 
/**
* Log the user out of the application.
*/
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つはパスワードが有効であることを確認し、ユーザーを目的の場所にリダイレクトするルートです。

lightbulb

次のドキュメントでは、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' => ['The provided password does not match our records.']
]);
}
 
$request->session()->passwordConfirmed();
 
return redirect()->intended();
})->middleware(['auth', 'throttle:6,1']);

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

ルートの保護

最近のパスワード確認を必要とするアクションを実行するルートには、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
{
// ...
 
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Auth::extend('jwt', function (Application $app, string $name, array $config) {
// Return an instance of 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構成ファイルで新しいユーザープロバイダーに切り替えることができます。まず、新しいドライバを使用するproviderを定義します。

'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メソッドに渡された資格情報の配列を受け取ります。その後、このメソッドは、それらの資格情報に一致するユーザーを検索するために、基盤となる永続ストレージを「クエリ」する必要があります。通常、このメソッドは、「username」が$credentials['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コントラクトを見てみましょう。覚えておいてください。ユーザープロバイダーは、retrieveByIdretrieveByToken、およびretrieveByCredentialsメソッドからこのインターフェースの実装を返す必要があります。

<?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ハッシュの「work factor」は、アプリケーションのconfig/hashing.php設定ファイルまたはBCRYPT_ROUNDS環境変数で調整できます。

通常、CPU/GPUの処理能力の向上に伴い、bcryptのwork factorは時間の経過とともに増やす必要があります。アプリケーションのbcrypt work factorを増やすと、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