Laravelの認証は、ウェブアプリケーションにおいて最も重要で不可欠な機能の1つです。Laravelをはじめとするウェブフレームワークには、さまざまなユーザー認証方法があります。

Laravelの認証機能は、素早く、安全な方法で実装可能です。しかし、適切に実装しなければ、悪意ある第三者に悪用される危険性があります。

この記事では、Laravelの認証機能を使用する際に、知っておくべきことをすべてご紹介します。

Laravelの認証入門

Laravelには、「ガード」と「プロバイダ」から構成されるモジュールがあります。ガードは各リクエストのユーザー認証を定義し、プロバイダは永続ストレージMySQLデータベースなど)からのユーザーの取得方法を定義します。

認証パラメータは、config/auth.phpファイルで定義します。このファイル内でLaravelの認証の振る舞いを調整、変更する複数のオプションを設定することができます。

まずは、デフォルトの認証を定義する必要があります。これが、アプリケーションのデフォルトのガードと、パスワードリセットを制御します。デフォルトは必要に応じて変更できますが、基本的にはデフォルトのままで問題ありません。

次に、アプリケーションのガードを定義します。この例では、デフォルトの設定として、セッションストレージとEloquentユーザープロバイダを使用します。すべての認証ドライバにはユーザープロバイダがあります。

<?php

return [
    /* 
    Defining Authentication Defaults  
    */
    
    'defaults' => [
        'guard' => 'web', 
        'passwords' => 'users',
    ],
    
    /*
    Defining Authentication Guards
   
    Supported: "session"
    */

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
     ],
    
    /*
    Defining User Providers

    Supported: "database", "eloquent"
    */

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

        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],

    /*
    Defining Password Resetting
    */

    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
            'throttle' => 60,
         ],
     ],

     /*
     Defining Password Confirmation Timeout
     */

    'password_timeout' => 10800,
];

この記事の後半で、すべての認証ドライバにユーザープロバイダがあることを確認していきます。プロバイダはユーザーの取得方法を定義し、ユーザーデータを永続化したデータベースや、その他のストレージ機構からユーザーを取得します。複数のユーザーテーブルやモデルがあれば、各モデルやテーブルを表す複数のソースを設定でき、必要に応じて、定義した任意のガードにソースを割り当てることができます。

ユーザーがパスワードをリセットしたい場合もあります。アプリケーションに複数のユーザーテーブルやモデルがあり、特定のユーザータイプに基づいて個別に設定したい場合は、複数のパスワードリセット構成を指定できます。有効期限は、各リセットトークンで有効な期間(分)です。このセキュリティ機能により、トークンの生存期間は短く保たれ、第三者に推測される時間を削減することができます。有効期間は必要に応じて変更可能です。

最後に、パスワードがタイムアウトし、確認画面を表示してユーザーにパスワードの再入力を求めるまでの時間を定義します。デフォルトでは3時間になっています。

Laravelの認証方法の種類

すべてのシナリオを認証する万能な方法はありませんが、それぞれの方法を知ることで、より良い判断ができます。Laravel 9で導入された新機能により、認証モードを切り替える操作が非常に簡単になりました。

パスワードベース認証

パスワードは、ユーザー認証の初歩的な方法であり、未だ何千もの組織で使用されています。しかし、現在の開発現場では、明らかに時代遅れになりつつあります。

サイト制作者は、複雑なパスワードの実装を徹底すると同時に、エンドユーザーの負担を最小限に抑えなければなりません。

パスワード認証は極めて単純に動作します。ユーザーは、ユーザー名とパスワードを入力し、それがデータベースに保存されている登録情報と一致すれば、サーバーがリクエストを認証します。すると、ユーザーはあらかじめ定義された期間、リソースにアクセスすることができます。

トークンベース認証

この方法は、認証時、ユーザーに一意のトークンを発行するものです。

トークンを持つユーザーは、その有効期限が切れるまで関連リソースにアクセスすることができます。

トークンが有効な間、ユーザー名やパスワードが不要ですが、新たにトークンを取得する際には必要になります。

トークンは今日、様々な場面で使用されています。これはトークンがすべての認証データを含む、ステートレスなエンティティであるためです。

トークンの生成と検証を分離する方法があることで、高い柔軟性を確保することができます。

多要素認証

多要素認証は、その名が示すとおり、少なくとも2つ以上の認証要素を組み合わせるもので、安全性を高めることができます。

2つの要素のみを使用する二要素認証とは異なり、多要素認証では2つ以上の要素を使用できます。

典型的な使用事例としては、まずパスワードを使用し、次にユーザーのスマートフォンに認証コードを送信します。多要素認証を導入する場合は、誤検知やネットワークの停止に注意が必要です。特に、事業規模を急速に拡大している場面では、大きな問題になる可能性があります。

Laravelで認証を実装する方法

このセクションでは、アプリケーションユーザーの認証方法をいくつかご説明します。Jetstream、Breeze、Socialiteなどのライブラリでは、無料の解説記事を公開しています。

手作業での認証

まずは、ユーザー登録から始めます。routes/web.phpに必要なルートを作成します。

フォーム表示用と登録用の2つのルートを作成します。

use App\Http\Controllers\Auth\RegisterController;
use Illuminate\Support\Facades\Route;

/*
Web Routes 

Register web routes for your app's RouteServiceProvider 
in a group containing the "web" middleware
*/

Route::get('/register', [RegisterController::class, 'create']);
Route::post('/register', [RegisterController::class, 'store']);

次に、コントローラを作成します。

php artisan make:controller Auth/RegisterController -r

生成されたコードを更新します。

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use illuminate\Htpp\Request;

class RegisterController extends Controller
{
    public function create()
    {
        return view('auth.register');
    }

    public function store(Request $request)
    {
    }
}

現在コントローラは空で、登録用のビューを返しています。そのビューをresources/views/authに作成し、名前をregister.blade.phpとします。

ユーザーを登録するLaravel Bladeビュー
ユーザーを登録するLaravel Bladeビュー

これですべてが整いました。/registerルートにアクセスすると、登録フォームが表示されます。

手作業での認証に利用できる登録フォームの様子
手作業での認証に利用できる登録フォームの様子

これでユーザー入力用のフォームを表示し、データを取得できます。次のコードでは、ユーザーのデータを取得、検証し、問題がなければデータベースに保存します。保存に際しては、データベーストランザクションを使用し、挿入するデータの完全性を担保します。

Laravelのリクエスト検証機能を使用して、3つの必須の認証情報がすべて入力されていることを確認します。また、メールアカウントは正しい形式で、usersテーブル内で一意であること、パスワードが有効で、8文字以上であることを確認します。

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;

class RegisterController extends Controller
{
    public function store(Request $request)
    {
        /* 
        Validation
        */
        $request->validate([
            'name' => 'required',
            'email' => 'required|email|unique:users',
            'password' => 'required|confirmed|min:8',
        ]);

        /*
        Database Insert
        */
        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password),
        ]);

        return back();
    }

    public function create()
    {
        return view('auth.register');
    }
}

これで入力の検証が行われ、検証に失敗するものがあればエラーが表示されるようになります。

登録の無効な入力の例
登録の無効な入力の例

storeメソッドでユーザーアカウントを作成したら、ユーザーにログインを要求します。これには、手作業で作成する方法と、Authファサードを使用する方法の2通りあります。

ユーザーがログインした後は、登録画面に戻るのではなく、ダッシュボードやホームページのような別のページに移動します。以下のコードでこれを行います。

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;

class RegisterController extends Controller
{
    public function store(Request $request)
    {
        /* 
        Validation
        */
        $request->validate([
            'name' => 'required',
            'email' => 'required|email|unique:users',
            'password' => 'required|confirmed|min:8',
        ]);

        /*
        Database Insert
        */
        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password),
        ]);

        Auth::login($user);

        return redirect(RouteServiceProvider::HOME);
    }

    public function create()
    {
        return view('auth.register');
    }
}

これでユーザーが登録され、ログインできる状態になったので、続いては安全にログアウトできるようにします。

Laravelはセキュリティ上の理由から、ログアウト後にセッションを無効にし、トークンを再生成することを推奨しています。まず、LogoutControllerdestroyメソッドを使用し、/logoutルートを作成します。

use App\Http\Controllers\Auth\RegisterController;
use App\Http\Controllers\Auth\LogoutController;
use Illuminate\Support\Facades\Route;

/*
Web Routes

Here is where you can register web routes for your application. These
routes are loaded by the RrouteServiceProvider with a group which
contains the "web" middleware group. Now create something great!
*/

Route::get('/register', [RegisterController::class, 'create']);
Route::post('/register', [RegisterController::class, 'store']);
Route::post('/logout', [Logoutcontroller::class, 'destroy'])
    ->middleware('auth');

ログアウトを「auth」ミドルウェアに渡すことは非常に重要です。これで、ログインしていないユーザーはルートにアクセスできなくなります。

先ほどと同じようにコントローラを作成します。

php artisan make:controller Auth/LogoutController -r

destroyメソッドのパラメータとして、リクエストを取得します。Authファサードを通してユーザーをログアウトし、セッションを無効化、トークンを再生成して、ホームページにリダイレクトするようにします。

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class LogoutController extends Controller
{
    public function destroy(Request $request)
    { 
        Auth::logout();

        $request->session()->invalidate();
        $request->session()->regenerateToken();
 
        return redirect('/');
     }
}

ユーザーの記憶

最近のほとんどのウェブアプリケーションには、ログインフォームに「remember me」(ユーザーを記憶する)チェックボックスがあります。

この「remember me」機能をサポートするには、attemptメソッドの第2引数にブール値を指定します。

この機能が有効な場合、ユーザーは無期限で、またはログアウトするまで認証されている状態になります。ユーザーテーブルは、文字列remember_tokenカラムを含む必要があり(そのためトークンの再生成が必要)、ここに「remember me」トークンを格納します。

ユーザー用のデフォルトのマイグレーションには、すでにこのカラムが含まれています。

まずフォームに、Remember Meフィールドを追加します。

フォームへの「Remember Me」フィールドの追加
フォームへの「Remember Me」フィールドの追加

次にリクエストから認証情報を取得し、Authファサードのattemptメソッドを使用します。

記憶されているユーザーは、ログイン後、ホームページにリダイレクトされます。そうでなければ、エラーを返します。

public function store(Request $request)
{
    $credentials = $request->only('email', 'password');

    if (Auth::attempt($credentials, $request->filled('remember'))) {
        $request->session()->regenerate();

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

    return back()->withErrors([
        'email' => 'The provided credentials do not match our records.',
    ]);
}

パスワードのリセット

今日、ほとんどのウェブアプリケーションには、ユーザーが自身でパスワードをリセットできる機能があります。

パスワードを忘れたユーザー向けに、新たに別のルートを作成し、先ほどと同じようにコントローラを作成します。さらに、プロセス全体のトークンを含む、パスワードのリセットリンク用のルートも追加していきます。

Route::post('/forgot-password', [ForgotPasswordLinkController::class, 'store']);
Route::post('/forgot-password/{token}', [ForgotPasswordController::class, 'reset']);

storeメソッドの内部でリクエストからメールアカウントを受け取り、先ほどと同じように検証します。

次に、PasswordファサードのsendResetLinkメソッドを使用します。

最後にレスポンスとして、リンクの送信に成功した場合はステータスを、失敗した場合はエラーを返します。

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Password;

class ForgotPasswordLinkController extends Controller
{
    public function store(Request $request)
    {
        $request->validate([
             'email' => 'required|email',
        ]);

        $status = Password::sendResetLink(
            $request->only('email');
        );

        return $status === Password::RESET_LINK_SENT
            ? back()->with('status', __($status))
            : back()->withInput($request->only('email'))->withErrors(['email' => __($status)]);
     }
}

ユーザーのメールアカウントにリセットリンクが送信されるようになったら、この後のロジックを作成します。

トークン、メールアカウント、新しいパスワードをリクエスト内で取得し、検証します。

この後は、Laravelですべての処理を行うため、Passwordファサードからresetメソッドを使用します。

パスワードは安全に保つため、常にハッシュ化します。

最後に、パスワードがリセットされたかどうかをチェックし、リセットされていれば、成功のメッセージと共にログイン画面にリダイレクトします。そうでなければ、リセットできなかった旨のエラーを表示します。

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Str;

class ForgotPasswordController extends Controller
{
    public function reset(Request $request)
    {
        $request->validate([
            'token' => 'required',
            'email' => 'required|email',
            'password' => 'required|string|confirmed|min:8',
        ]);

        $status = Password::reset(
            $request->only('email', 'password', 'password_confirmation', 'token'),
            function ($user) use ($request) {
                $user->forceFill(
                    'password' => Hash::make($request->password),
                    'remember_token' => Str::random(60)
                ])->save();
            }
        );

        return $status == Password::PASSWORD_RESET
            ? redirect()->route('login')->with('status', __($status))
            : back()->withInput($request->only('email'))->withErrors(['email' => __($status)]);
    }
}

Laravel Breeze

Laravel Breezeは、Laravelの認証機能(ログイン、登録、パスワードリセット、メール認証、パスワードの確認)を簡単に実装できるパッケージです。新規作成したLaravelアプリケーションへの実装に使用できます。

インストールとセットアップ

Laravelアプリケーションを作成したら、データベースを構成し、マイグレーションを実行して、composerでlaravel/breezeパッケージをインストールします。

composer require laravel/breeze --dev

次に、以下を実行します。

php artisan breeze:install

これにより、認証ビュー、ルート、コントローラ、およびその他のリソースが公開されます。この後、Breezeのすべての機能を完全に制御できるようになります。

次に、フロントエンドでアプリケーションをレンダリングするため、JSの依存関係をインストールします(@viteを使用します)。

npm install

:

npm run dev

これで、ログインと登録のリンクがホームページに表示され、以後、すべてスムーズに動作するはずです。

Laravel Jetstream

Laravel Jetstreamは、便利な機能や他のフロントエンドスタックを使用して、Laravel Breezeを拡張することができます。

ログイン、登録、メール認証、二要素認証、セッション管理、Sanctum経由のAPIサポート、およびチーム管理(任意)をサポートしています。

Jetstreamをインストールする際、フロントエンドでLivewireとInertiaのどちらかを選択します。バックエンドでは、Laravel Fortifyを使用します。Fortifyはフロントエンドに依存しない、Laravelの「ヘッドレス」認証バックエンドです。

インストールとセットアップ

LaravelプロジェクトにComposerを使用して、Jetstreamをインストールします。

composer require laravel/jetstream

この後、php artisan jetstream:install [stack]コマンドを実行します。このとき、[stack]引数には、LivewireまたはInertiaを指定してください。チーム機能を有効にするには、--teamsオプションを指定します。

これでテスト用のPest PHPもインストールされます。

最後に、アプリケーションのフロントエンドをレンダリングします。

npm install
npm run dev

Laravel Fortify

Laravel Fortifyは、フロントエンドに依存しない認証バックエンドを実装するパッケージで、Laravelの認証機能の実装において必須ではありません。

Laravel Fortifyは、BreezeやJetstreamなどのスターターキットでも使用されています。スタンドアロンでも使用できますが、この場合は単なるバックエンド実装となり、フロントエンドでFortifyルートを呼び出さなければなりません。

インストールとセットアップ

Composerを使用してFortifyをインストールします。

composer require laravel/fortify

次に、Fortifyのリソースを公開します。

php artisan vendor:publish --provider="Laravel\Fortify\FortifyServiceProvider"

この後、新規app/Actionsディレクトリや、FortifyServiceProvider、設定ファイル、データベースのマイグレーションを作成します。

最後に以下を実行します。

php artisan migrate

または以下でもOKです。

php artisan migrate:fresh

これでFortifyの準備ができました。

Laravel Socialite

Laravelには、簡単なOAuthベースのユーザー認証機能があり、FacebookTwitterLinkedIn、Google、Bitbucket、GitHub、GitLab経由のソーシャルログインをサポートすることができます。

インストール

Socialiteは、Composerを使用してインストールできます。

composer require laravel/socialite

セットアップと使用方法

インストールが完了したら、アプリケーションが使用するOAuthプロバイダの認証情報を各サービスのconfig/services.phpに追加します。

構成では、以前のサービスとキーが一致しなければなりません。キーには以下のようなものがあります。

  • facebook
  • twitter (For OAuth 1.0)
  • twitter-oauth-2 (For OAuth 2.0)
  • linkedin
  • google
  • github
  • gitlab
  • bitbucket

サービスの構成例は、次のようになります。

'google' => [
    'client_id' => env("GOOGLE_CLIENT_ID"),
    'client_secret' => env("GOOGLE_CLIENT_SECRET"),
    'redirect' => "http://example.com/callback-url",
],

ユーザーの認証

このアクションには、2つのルートが必要です。1つはユーザーをOAuthプロバイダにリダイレクトします。

use Laravel\Socialite\Facades\Sociliate;

Route::get('/auth/redirect', function () {
    return Socialite::driver('google')->redirect();
});

もう1つは、認証後のプロバイダからのコールバックです。

use Laravel\Socialite\Facades\Socialite;

Route:;get('/auht/callback', function () {
    $user = Socialite::driver('google')->user();

    // Getting the user data
    $user->token;
});

Socialiteにはredirectメソッドがあり、ファサードはユーザーをOAuthプロバイダにリダイレクトします。userメソッドは入力されたリクエストを検査し、ユーザー情報を取得します。

ユーザー情報を取得したら、データベースにそのユーザーが存在するかを確認し、認証を行います。存在しなければ、ユーザーを表すレコードを新規作成します。

use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Laravel\Socialite\Facades\Socialite;

Route::get('/auth/callback', function () {
   /*
   Get the user
   */
   $googleUser = Socialite::driver('google')->user();
   
   /*
   Create the user if it does not exist
   Update the user if it exists
   
   Check for google_id in database
   */
   $user = User::updateOrCreate([
       'google_id' => $googleUser->id,
   ], [
       'name' => $googleUser->name,
       'email' => $googleUser->email,
       'google_token' => $googleUser->token,
       'google_refresh_token' => $googleUser->refreshToken,
   ]);

   /*
   Authenticates the user using the Auth facade
   */
    Auth::login($user);
   
    return redirect('/dashboard');
});

ユーザーのアクセススコープを制限するには、認証リクエストに含めるscopesメソッドを使用します。以前に指定したすべてのスコープを、指定したスコープに統合します。

代替としてsetScopesメソッドを使用すると、既存のすべてのスコープを上書きできます。

use Laravel\Socialite\Facades\Socialite;

return Socialite::driver('google')
    ->scopes(['read:user', 'write:user', 'public_repo'])
    ->redirect();

return Socialite::driver('google')
    ->setScopes(['read:user', 'public_repo'])
    ->redirect();

コールバック後にユーザーを取得する方法がわかったところで、取得できるデータを見てみます。

OAuth1 Userには、tokentokenSecretがあります。

$user = Socialite::driver('google')->user();

$token = $user->token;
$tokenSecret = $user->tokenSecret;

OAuth2には、tokenrefreshTokenexpiresInがあります。

$user = Socialite::driver('google')->user();

$token = $user->token;
$refreshToken = $user->refreshToken;
$expiresIn = $user->expiresIn;

OAuth1にもOAuth2にも、getIdgetNicknamegetNamegetEmailgetAvatarがあります。

$user = Socialite::driver('google')->user();

$user->getId();
$user->getNickName();
$user->getName();
$user->getEmail();
$user->getAvatar();

Socialiteにはトークン(OAuth 2)、またはトークンとシークレット(OAuth 1)からユーザー情報を取得する2つのメソッド、userFromTokenuserFromTokenAndSecretがあります。

use Laravel\Socialite\Facades\Socialite;

$user = Socialite::driver('google')->userFromToken($token);
$user = Socialite::driver('twitter')->userFromTokenAndSecret($token, $secret);

Laravel Sanctum

Laravel Sanctumは、SPA(シングルページアプリケーション)やモバイルアプリケーション向けの軽量な認証システム。特定のスコープを持つ複数のAPIトークンを生成することができます。スコープは、トークンによって許可されるアクションを指定します。

使用方法

Sanctumを使用すると、OAuthのような複雑な手続きなしで、ユーザーにAPIトークンを発行することができます。トークンの有効期限は、通常年単位と長期的ですが、いつでも取り消して再生成することができます。

インストールとセットアップ

SanctumはComposerを使用してインストールします。

composer require laravel/sanctum

次に、構成ファイルとマイグレーションファイルを公開します。

php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"

マイグレーションファイルを生成できたので、マイグレーションします。

php artisan migrate:fresh

APIトークンの発行方法

トークンを発行する前に、UserモデルはLaravel\Sanctum\HasApiTokensトレイトを使用する必要があります。

use Laravel\Sanctum\HasApiTokens;

class User extends Authenticable
{
    use HasApiTokens;
}

ユーザーを取得したら、トークンを発行することができます。createTokenメソッドを呼び出すと、Laravel\Sanctum\NewAccessTokenインスタンスが返されます。

NewAccessTokenインスタンスでplainTextTokenメソッドを呼び出すと、トークンのSHA-256プレーンテキスト値が表示されます。

Laravelの認証にまつわるヒントとベストプラクティス

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

前述したように、ユーザーがログアウトした際、セッションを無効化することは重要ですが、これは所有するすべてのデバイスについても同様です。

この機能は通常、ユーザーがパスワードを変更、更新した際、他のデバイスからのセッションを無効化します。

Authファサードを使用すると、この機能を簡単に実装できます。今回の例のルートには、authauth.sessionミドルウェアがあるため、ファサードのlogoutOtherDevices静的メソッドを使用します。

Route::get('/logout', [LogoutController::class, 'invoke'])
    ->middleware(['auth', 'auth.session']);

use Illuminate\Support\Facades\Auth;

Auth::logoutOtherDevices($password);

Auth::routes()による構成

Authファサードのroutesメソッドは、ユーザー認証に必要なすべてのルートを生成するヘルパーに過ぎません。

ルートには、Login(Get、Post)、Logout(Post)、Register(Get、Post)、Password Reset/Email(Get、Post)があります。

ファサードのメソッドを呼び出すと、次のような処理が行われます。

public static function routes(array $options = [])
{
    if (!static::$app->providerIsLoaded(UiServiceProvider::class)) {
        throw new RuntimeException('In order to use the Auth:;routes() method, please install the laravel/ui package.');
    }
   
    static::$app->make('router')->auth($options);
}

では、ルーター上で静的メソッドが呼び出されると、どうなるのでしょうか。ファサードの動きのため少々複雑ですが、次のようになります。

/**
Register the typical authentication routes for an application.

@param array $options
@return void
*/
public function auth(array $options = [])
{
    // Authentication Routes...
    $this->get('login', 'Auth\LoginController@showLoginForm')->name('login');
    $this->post('login', 'Auth\LoginController@login');
    $this->post('logout', 'Auth\LoginController@logout')->name('logout');

    // Registration Routes...
    if ($options['register'] ?? true) {
        $this->get('register', 'Auth\RegisterController@showRegistrationForm')->name('register');
        $this->post('register', 'Auth\RegisterController@register');
    }
   
    // Password Reset Routes...
    if ($options['reset'] ?? true) {
        $this->resetPassword();
    }

    // Email Verification Routes...
    if ($options['verify'] ?? false) {
        $this->emailVerification();
    }
}   

デフォルトでは、メール検証ルート以外のすべてのルートが生成されます。ログインとログアウトのルートは常に生成されますが、その他のルートはオプション配列で制御することができます。

ログイン、ログアウト、登録だけを行うには、次のオプション配列を指定します。

$options = ["register" => true, "reset" => false, "verify" => false];

ルートの保護とカスタムガード

認証されたユーザーのみが特定のルートにアクセスできるようにするには、Routeファサードでミドルウェアメソッドを呼び出すか、ミドルウェアメソッドをチェーンします。

Route::middleware('auth')->get('/user', function (Request $request) {
    return $request->user();
});

Route::get('/user', function (Request $request) {
    return $request->user();
})->middleware('auth');

このガードは、到着したリクエストが認証されていることを保証します。

パスワードの確認

ウェブサイトのセキュリティ強化のため、他のタスクに進む前に、ユーザーのパスワードを確認したい場合があります。

リクエストを処理するには、パスワード確認ビューからルートを定義しなければなりません。このルートはユーザーを検証し、目的地にリダイレクトします。同時に、パスワードがセッションで確認されるようにします。デフォルトでパスワードは、3時間ごとに再確認されますが、これはconfig/auth.phpの設定ファイルで変更可能です。

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']);

Authenticableコントラクト

Illuminate\Contracts\AuthにあるAuthenticableコントラクトは、UserProviderファサードが実装するひな形を定義します。

namespace Illuminate\Contracts\Auth;

interface Authenticable 
{
    public function getAuthIdentifierName();
    
    public function getAuthIdentifier();
    
    public function getAuthPassord();
  
    public function getRememberToken();

    public function setRememberToken($value);
  
    public function getrememberTokenName();
}

認証システムは、このインターフェースを実装した任意の「ユーザー」クラスと連携することができます。

この連携は、どのORMやストレージレイヤーが使われているかに関係なく保持されます。Laravelには、デフォルトでこのインターフェースを実装するApp\Models\Userがあり、構成ファイル内でも確認できます。

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

認証イベント

認証プロセスを通じて送られるイベントは、多数あります。

目的に応じて、EventServiceProvider内のイベントにリスナーを接続することができます。

認証サービス用に生成されたLaravelリスナー一覧
認証サービス用に生成されたLaravelリスナー一覧

シンプルなユーザー作成

新規ユーザーを素早く作成するには、App\Userを使用します。

$user = new App\User();
$user->password = Hash::make('strong_password');
$user->email = '[email protected]';
$user->name = 'Username';
$user->save();

または、Userファサードのcreate静的メソッドを使用します。

User::create([
 'password' => Hash::make('strong-password'),
 'email' => '[email protected]',
 'name' => 'username'
]);

まとめ

Laravelエコシステムには、BreezeやJetstreamのような、認証システムを使用したアプリケーションの開発、稼働を支援する、多数のスターターキットがあります。開発者側にコードが生成されるため、高度なカスタマイズが可能になり、必要であればひな形として使用して、自由に編集することができます。

認証方式やその実装の複雑さには、多くのセキュリティ上の懸念がありますが、Laravelのツールを使用すれば、簡単に解決可能。カスタマイズ性が高く、使い勝手にも優れています。

Kinstaの高速Laravelホスティングでは、Laravelアプリを効率的に公開することができます。まずは無料利用枠で、アプリケーションの動作をお確かめください

Coman Cosmin

3年以上の経験を持つテクニカルライター、開発者。Kinstaでの執筆以外には、核物理学施設や大学での研究を支援。技術に精通し、コミュニティで活発に活動しており、常に革新的なソリューションを考案している。