認証
- はじめに
- 認証クイックスタート
- ユーザーの手動認証
- HTTP基本認証
- ログアウト
- パスワード確認
- カスタムガードの追加
- カスタムユーザープロバイダの追加
- 自動パスワード再ハッシュ
- ソーシャル認証
- イベント
はじめに
多くのウェブアプリケーションは、ユーザーがアプリケーションで認証して「ログイン」する方法を提供しています。ウェブアプリケーションでこの機能を実装することは、複雑でリスクを伴う可能性があります。このため、Laravelは、認証を迅速、安全、かつ容易に実装するために必要なツールを提供することに努めています。
Laravelの認証機能の中核は、「ガード」と「プロバイダ」で構成されています。ガードは、各リクエストに対してユーザーがどのように認証されるかを定義します。たとえば、Laravelには、セッションストレージとCookieを使用して状態を維持するsession
ガードが付属しています。
プロバイダは、永続的なストレージからユーザーがどのように取得されるかを定義します。Laravelは、Eloquentとデータベースクエリビルダーを使用してユーザーを取得するためのサポートを提供しています。ただし、アプリケーションの必要に応じて追加のプロバイダを自由に定義できます。
アプリケーションの認証設定ファイルは、config/auth.php
にあります。このファイルには、Laravelの認証サービスの動作を微調整するためのいくつかのよく文書化されたオプションが含まれています。
ガードとプロバイダは、「ロール」と「権限」と混同しないでください。権限によるユーザーアクションの認可の詳細については、認可ドキュメントを参照してください。
スターターキット
迅速に開始したいですか?新しい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 Breeze、Laravel 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 CSS、Livewire、および/またはInertiaによって強化された美しくモダンなUIを使用して、Laravel Fortifyの認証サービスを利用および公開する堅牢なアプリケーションスターターキットです。Laravel Jetstreamには、2要素認証、チームサポート、ブラウザセッション管理、プロファイル管理、およびLaravel Sanctumとの組み込み統合(APIトークン認証を提供)のオプションサポートが含まれています。LaravelのAPI認証機能については、以下で説明します。
LaravelのAPI認証サービス
Laravelは、APIトークンの管理とAPIトークンを使用したリクエストの認証を支援する2つのオプションパッケージを提供しています。 PassportとSanctumです。これらのライブラリと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を推奨いたします。
認証クイックスタート
ドキュメントのこの部分は、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...}
`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アドレスに固有です。
アプリケーションの他のルートにレート制限を適用したい場合は、レート制限ドキュメントを参照してください。
ユーザーの手動認証
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...}
これらの例では、`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つはパスワードが有効であることを確認し、ユーザーを目的の場所にリダイレクトするルートです。
次のドキュメントでは、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
メソッドを使用することです。このメソッドを使用すると、単一のクロージャを使用して認証プロセスを迅速に定義できます。
開始するには、アプリケーションのAppServiceProvider
のboot
メソッド内で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
コントラクトを見てみましょう。覚えておいてください。ユーザープロバイダーは、retrieveById
、retrieveByToken
、および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 |