コンテンツへスキップ

認証

イントロダクション

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

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

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

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

ガードとプロバイダを「ロール」と「パーミッション」と混同しないでください。パーミッションを介したユーザーアクションの認可について詳しく知りたい場合は、認可のドキュメントを参照してください。

スターターキット

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

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

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

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

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

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

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

エコシステムの概要

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

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

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

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

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

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

このドキュメントで説明しているように、これらの認証サービスを手動で操作して、アプリケーション独自の認証レイヤーを構築できます。ただし、より迅速に開始できるように、認証レイヤー全体の堅牢でモダンなスキャフォールディングを提供する無料のスターターキットをリリースしました。

LaravelのAPI認証サービス

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

Passport

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

Sanctum

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

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

まとめとスタックの選択

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

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

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

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

そして、すぐに始めたい場合は、推奨するLaravelの組み込み認証サービスの認証スタックをすでに使用している新しいLaravelアプリケーションを開始する簡単な方法として、アプリケーションスターターキットをお勧めします。

認証クイックスタート

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

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

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

認証済みユーザーの取得

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

1use Illuminate\Support\Facades\Auth;
2 
3// Retrieve the currently authenticated user...
4$user = Auth::user();
5 
6// Retrieve the currently authenticated user's ID...
7$id = Auth::id();

または、ユーザーが認証されると、Illuminate\Http\Requestインスタンスを介して認証済みユーザーにアクセスできます。タイプヒントされたクラスは自動的にコントローラメソッドにインジェクトされることを忘れないでください。Illuminate\Http\Requestオブジェクトをタイプヒントすることで、リクエストのuserメソッドを介して、アプリケーションの任意のコントローラメソッドから認証済みユーザーに簡単にアクセスできます。

1<?php
2 
3namespace App\Http\Controllers;
4 
5use Illuminate\Http\RedirectResponse;
6use Illuminate\Http\Request;
7 
8class FlightController extends Controller
9{
10 /**
11 * Update the flight information for an existing flight.
12 */
13 public function update(Request $request): RedirectResponse
14 {
15 $user = $request->user();
16 
17 // ...
18 
19 return redirect('/flights');
20 }
21}

現在のユーザーが認証済みかどうかを判断する

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

1use Illuminate\Support\Facades\Auth;
2 
3if (Auth::check()) {
4 // The user is logged in...
5}

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

ルートの保護

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

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

未認証ユーザーのリダイレクト

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

1use Illuminate\Http\Request;
2 
3->withMiddleware(function (Middleware $middleware) {
4 $middleware->redirectGuestsTo('/login');
5 
6 // Using a closure...
7 $middleware->redirectGuestsTo(fn (Request $request) => route('login'));
8})

ガードの指定

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

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

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

私たちのアプリケーションスターターキットのいずれかを使用している場合、レート制限はログイン試行に自動的に適用されます。デフォルトでは、ユーザーは数回の試行の後に正しい資格情報を提供できなかった場合、1分間ログインできなくなります。スロットリングは、ユーザーのユーザー名/メールアドレスとそのIPアドレスに固有です。

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

ユーザーの手動認証

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

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

1<?php
2 
3namespace App\Http\Controllers;
4 
5use Illuminate\Http\Request;
6use Illuminate\Http\RedirectResponse;
7use Illuminate\Support\Facades\Auth;
8 
9class LoginController extends Controller
10{
11 /**
12 * Handle an authentication attempt.
13 */
14 public function authenticate(Request $request): RedirectResponse
15 {
16 $credentials = $request->validate([
17 'email' => ['required', 'email'],
18 'password' => ['required'],
19 ]);
20 
21 if (Auth::attempt($credentials)) {
22 $request->session()->regenerate();
23 
24 return redirect()->intended('dashboard');
25 }
26 
27 return back()->withErrors([
28 'email' => 'The provided credentials do not match our records.',
29 ])->onlyInput('email');
30 }
31}

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

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

認証が成功した場合、attemptメソッドはtrueを返します。それ以外の場合は、falseが返されます。

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

追加条件の指定

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

1if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) {
2 // Authentication was successful...
3}

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

1use Illuminate\Database\Eloquent\Builder;
2 
3if (Auth::attempt([
4 'email' => $email,
5 'password' => $password,
6 fn (Builder $query) => $query->has('activeSubscription'),
7])) {
8 // Authentication was successful...
9}

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

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

1if (Auth::attemptWhen([
2 'email' => $email,
3 'password' => $password,
4], function (User $user) {
5 return $user->isNotBanned();
6})) {
7 // Authentication was successful...
8}

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

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

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

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

ユーザーの記憶

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

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

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

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

1use Illuminate\Support\Facades\Auth;
2 
3if (Auth::viaRemember()) {
4 // ...
5}

その他の認証方法

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

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

1use Illuminate\Support\Facades\Auth;
2 
3Auth::login($user);

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

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

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

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

IDによるユーザー認証

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

1Auth::loginUsingId(1);

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

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

一度だけユーザーを認証する

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

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

HTTP基本認証

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

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

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

FastCGIに関する注意

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

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

ステートレスHTTP基本認証

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

1<?php
2 
3namespace App\Http\Middleware;
4 
5use Closure;
6use Illuminate\Http\Request;
7use Illuminate\Support\Facades\Auth;
8use Symfony\Component\HttpFoundation\Response;
9 
10class AuthenticateOnceWithBasicAuth
11{
12 /**
13 * Handle an incoming request.
14 *
15 * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
16 */
17 public function handle(Request $request, Closure $next): Response
18 {
19 return Auth::onceBasic() ?: $next($request);
20 }
21 
22}

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

1Route::get('/api/user', function () {
2 // Only authenticated users may access this route...
3})->middleware(AuthenticateOnceWithBasicAuth::class);

ログアウト

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

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

1use Illuminate\Http\Request;
2use Illuminate\Http\RedirectResponse;
3use Illuminate\Support\Facades\Auth;
4 
5/**
6 * Log the user out of the application.
7 */
8public function logout(Request $request): RedirectResponse
9{
10 Auth::logout();
11 
12 $request->session()->invalidate();
13 
14 $request->session()->regenerateToken();
15 
16 return redirect('/');
17}

他のデバイスのセッションを無効にする

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

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

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

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

1use Illuminate\Support\Facades\Auth;
2 
3Auth::logoutOtherDevices($currentPassword);

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

パスワードの確認

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

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

設定

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

ルーティング

パスワード確認フォーム

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

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

ご想像のとおり、このルートによって返されるビューには、passwordフィールドを含むフォームが必要です。さらに、ユーザーがアプリケーションの保護されたエリアに入っており、パスワードを確認する必要があることを説明するテキストをビューに自由に追加してください。

パスワードの確認

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

1use Illuminate\Http\Request;
2use Illuminate\Support\Facades\Hash;
3use Illuminate\Support\Facades\Redirect;
4 
5Route::post('/confirm-password', function (Request $request) {
6 if (! Hash::check($request->password, $request->user()->password)) {
7 return back()->withErrors([
8 'password' => ['The provided password does not match our records.']
9 ]);
10 }
11 
12 $request->session()->passwordConfirmed();
13 
14 return redirect()->intended();
15})->middleware(['auth', 'throttle:6,1']);

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

ルートの保護

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

1Route::get('/settings', function () {
2 // ...
3})->middleware(['password.confirm']);
4 
5Route::post('/settings', function () {
6 // ...
7})->middleware(['password.confirm']);

カスタムガードの追加

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

1<?php
2 
3namespace App\Providers;
4 
5use App\Services\Auth\JwtGuard;
6use Illuminate\Contracts\Foundation\Application;
7use Illuminate\Support\Facades\Auth;
8use Illuminate\Support\ServiceProvider;
9 
10class AppServiceProvider extends ServiceProvider
11{
12 // ...
13 
14 /**
15 * Bootstrap any application services.
16 */
17 public function boot(): void
18 {
19 Auth::extend('jwt', function (Application $app, string $name, array $config) {
20 // Return an instance of Illuminate\Contracts\Auth\Guard...
21 
22 return new JwtGuard(Auth::createUserProvider($config['provider']));
23 });
24 }
25}

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

1'guards' => [
2 'api' => [
3 'driver' => 'jwt',
4 'provider' => 'users',
5 ],
6],

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

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

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

1use App\Models\User;
2use Illuminate\Http\Request;
3use Illuminate\Support\Facades\Auth;
4 
5/**
6 * Bootstrap any application services.
7 */
8public function boot(): void
9{
10 Auth::viaRequest('custom-token', function (Request $request) {
11 return User::where('token', (string) $request->token)->first();
12 });
13}

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

1'guards' => [
2 'api' => [
3 'driver' => 'custom-token',
4 ],
5],

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

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

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

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

1<?php
2 
3namespace App\Providers;
4 
5use App\Extensions\MongoUserProvider;
6use Illuminate\Contracts\Foundation\Application;
7use Illuminate\Support\Facades\Auth;
8use Illuminate\Support\ServiceProvider;
9 
10class AppServiceProvider extends ServiceProvider
11{
12 // ...
13 
14 /**
15 * Bootstrap any application services.
16 */
17 public function boot(): void
18 {
19 Auth::provider('mongo', function (Application $app, array $config) {
20 // Return an instance of Illuminate\Contracts\Auth\UserProvider...
21 
22 return new MongoUserProvider($app->make('mongo.connection'));
23 });
24 }
25}

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

1'providers' => [
2 'users' => [
3 'driver' => 'mongo',
4 ],
5],

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

1'guards' => [
2 'web' => [
3 'driver' => 'session',
4 'provider' => 'users',
5 ],
6],

ユーザープロバイダ契約

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

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

1<?php
2 
3namespace Illuminate\Contracts\Auth;
4 
5interface UserProvider
6{
7 public function retrieveById($identifier);
8 public function retrieveByToken($identifier, $token);
9 public function updateRememberToken(Authenticatable $user, $token);
10 public function retrieveByCredentials(array $credentials);
11 public function validateCredentials(Authenticatable $user, array $credentials);
12 public function rehashPasswordIfRequired(Authenticatable $user, array $credentials, bool $force = false);
13}

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

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

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

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

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

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

Authenticatable契約

UserProviderの各メソッドを調べたので、次はAuthenticatable契約を見てみましょう。ユーザープロバイダは、retrieveByIdretrieveByToken、およびretrieveByCredentialsメソッドからこのインターフェースの実装を返す必要があることを忘れないでください。

1<?php
2 
3namespace Illuminate\Contracts\Auth;
4 
5interface Authenticatable
6{
7 public function getAuthIdentifierName();
8 public function getAuthIdentifier();
9 public function getAuthPasswordName();
10 public function getAuthPassword();
11 public function getRememberToken();
12 public function setRememberToken($value);
13 public function getRememberTokenName();
14}

このインターフェースは単純です。getAuthIdentifierNameメソッドは、ユーザーの「主キー」カラムの名前を返し、getAuthIdentifierメソッドは、ユーザーの「主キー」を返す必要があります。MySQLバックエンドを使用する場合、これはおそらくユーザーレコードに割り当てられた自動インクリメントの主キーになります。getAuthPasswordNameメソッドは、ユーザーのパスワードカラムの名前を返す必要があります。getAuthPasswordメソッドは、ユーザーのハッシュ化されたパスワードを返す必要があります。

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

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

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

通常、CPU/GPUの処理能力が向上するにつれて、bcryptのワークファクターは時間とともに増加させる必要があります。アプリケーションのbcryptワークファクターを増やすと、Laravelは、ユーザーがLaravelのスターターキットを介してアプリケーションで認証するとき、またはユーザーを手動で認証するときに、attemptメソッドを介して、ユーザーのパスワードを適切かつ自動的に再ハッシュします。

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

1php artisan config:publish hashing

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

1'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

Laravelは最も生産的な方法です
ソフトウェアを構築、デプロイ、監視します。