🙄

Laravel BreezeとInertia.jsで二段階認証を実装してみる - SMS送信編-

2024/09/10に公開

Laravel BreezeとVonageを使った二段階認証(SMS送信)の実装

この記事では、前回メールで実装した二段階認証を、SMSに置き換えて実装する方法について説明します。
今回は、Laravel BreezeとVonage(旧称:Nexmo)のAPIを使用して、SMSで認証コードを送信するシンプルな方法を紹介します。

前回の記事はこちら
Laravel BreezeとInertia.jsで二段階認証を実装してみる

1. 必要な準備

まず、SMSを送信するためにVonageのライブラリをインストールします。以下のコマンドを実行してください。

$ composer require laravel/vonage-notification-channel guzzlehttp/guzzle

VonageのAPIを利用するために、.env ファイルにAPIキーと送信者名(または送信元番号)を設定します。

.env
VONAGE_KEY=your_api_key
VONAGE_SECRET=your_api_secret
VONAGE_SMS_FROM=your_sender_name_or_number

次に、config/services.php でVonageの設定を追加します。

config/services.php
'vonage' => [
    'key' => env('VONAGE_KEY'),
    'secret' => env('VONAGE_SECRET'),
    'sms_from' => env('VONAGE_SMS_FROM'),
],

2. SMS通知用のNotificationクラス作成

SendSms という通知クラスを作成し、以下のように実装します。このクラスは、SMSで認証コードを送信するためのものです。

$ ./vendor/bin/sail artisan make:notification SendSms
Norifications/SendSms.php
<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\VonageMessage;
use Illuminate\Notifications\Notification;

class SendSms extends Notification
{
    use Queueable;

    protected $code;

    public function __construct($code)
    {
        $this->code = $code;
    }

    public function via($notifiable)
    {
        return ['vonage'];
    }

    public function toVonage($notifiable)
    {
        return (new VonageMessage)
            ->from('TestApp')
            ->content("Your authentication code is: {$this->code}. It is valid for 10 minutes.")
            ->unicode();  // 日本語のメッセージを送信する場合はこの行を追加
    }
}

3. 二段階認証コードの生成とSMS送信

次に、TwoFactorAuthenticate クラスで、認証コードを生成し、SMSを送信するメソッドを作成します。

Utils/TwoFactorAuthenticate.php
<?php

use App\Models\User;
use Carbon\Carbon;

class TwoFactorAuthenticate
{
    public static function sendSms(User $user): void
    {
        $twoFactorAuthCode = random_int(100000, 999999);

        $user->two_factor_auth_code = $twoFactorAuthCode;
        $user->two_factor_auth_code_expires_at = Carbon::now()->addMinutes(10);
        $user->save();

        $user->notify(new SendSms($twoFactorAuthCode));
    }
}

4. UserモデルでのSMSルーティング

ユーザーの電話番号にSMSを送信するために、User モデルに以下のメソッドを追加します。

Models/User.php
public function routeNotificationForVonage(): string
{
    return $this->tel;  // SMS送信先の電話番号
}

5. 電話番号の国際フォーマットへの変換

SMS送信の際には、電話番号を国際フォーマット(例:日本の場合は+81)に変換する必要があります。RegisteredUserController にて、この変換を行います。

Auth/RegisteredUserController.php
public function store(Request $request): RedirectResponse
{
    $request->validate([
        'name' => 'required|string|max:255',
        'email' => 'required|string|lowercase|email|max:255|unique:'.User::class,
        'password' => ['required', 'confirmed', Rules\Password::defaults()],
        'tel' => 'required|string|max:255',
    ]);

    // 日本の電話番号を国際フォーマットに変換
    $tel = preg_replace('/^0/', '+81', $request->tel);

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

    event(new Registered($user));

    Auth::login($user);

    // SMSで認証コードを送信
    TwoFactorAuthenticate::sendSms($user);

    return redirect(route('dashboard', absolute: false));
}

6. TwoFactorAuthenticate::sendMail($user);の書き換え

Controllerのメール送信をSMS送信に変更します。

-        TwoFactorAuthenticate::sendMail($user);
+        TwoFactorAuthenticate::sendSms($user);

7. まとめ

今回の記事では、Laravel BreezeとVonageを使用してSMSによる二段階認証の実装方法について解説しました。
また、今回の実装における変更点や実際のコードは、下記リンクでGitHubリポジトリの差分からご確認いただけます。
差分はこちら

Discussion