Laravelを使ったAPIサーバーでメールアドレス認証を実装する

Laravel
language

この記事ではLaravelを使ったAPIサーバーでメールアドレス認証を実装する方法をご紹介します。

今回はLaravel5.7から新たに実装されたMustVerifyEmailインターフェースを使います。
MustVerifyEmailインターフェースを実装することで確認メール送信が自動で行われ、メール送信工程が省けるので非常に便利です。

UserモデルにMustVerifyEmailを実装

UserモデルではMustVerifyEmailを以下のコードのように入れる必要があります。

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable implements MustVerifyEmail
{
    use HasFactory, Notifiable;

    ...
}

MustVerifyEmailをUserモデルのインターフェースに実装するとメール確認通知が自動的に送信されます。

Email Verification - Laravel - The PHP Framework For Web Artisans

RegisterControllerで新規登録後にアクセストークンを作成

RegisterControllerのregisterメソッドを編集していきます。

以下のコードではユーザーを新規作成後(email_verified_atはnull)にその情報を返しています。

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use App\Models\User;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Session;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Auth\Events\Registered;

class RegisterController extends Controller
{
    ...

    public function register(Request $request): JsonResponse
    {
        $validate = $this->validator($request->all());

        if ($validate->fails()) {
            return new JsonResponse($validate->errors());
        }

        event(new Registered($user = $this->create($request->all())));

        // 新規作成後自動ログイン
        $this->guard()->login($user);

        return new JsonResponse(['user' => $user]);
    }
}

メールアドレス認証ルーティング

認証用のURLは以下のとおりです。
認証メールに記載される認証ボタンをクリックするとこのルーティングのURLが開いて、VerifyEmailControllerで認証後にリダイレクトされます。

// メールアドレス認証
Route::get('/email/verify/{id}/{hash}', [VerifyEmailController::class, '__invoke'])
    ->middleware(['signed', 'throttle:6,1'])
    ->name('verification.verify');

認証メールの再送が必要場合は以下のルーティングにポストすると認証メールが再送されます。

// メールアドレス認証メール再送
Route::post('/email/verify/resend', function (Request $request) {
    $request->user()->sendEmailVerificationNotification();
    return back()->with('message', 'Verification link sent!');
})->middleware(['auth:api', 'throttle:6,1'])->name('verification.send');

メールアドレス認証済みのアカウントのみAPIリクエストを受け付けたい場合は、ミドルウェアのverifiedで保護する必要があります。

Route::middleware(['verified'])->group(function(){
    // メールアドレス認証済みユーザーのみアクセス可能

});

メールアドレス認証が終わっていないアカウントをログインさせたくない場合はLoginController$this->getGuard()->user()->hasVerifiedEmail()を使ってログインを保護する必要があります。

class LoginController extends Controller
{
    ...

    public function login(Request $request): JsonResponse
    {
        $credentials = $request->validate([
            'email' => ['required', 'email'],
            'password' => 'required',
        ]);

        if ($this->getGuard()->attempt($credentials) && $this->getGuard()->user()->hasVerifiedEmail()) {
            $request->session()->regenerate();

            return new JsonResponse(['message' => 'ログインしました']);
        }

        throw new Exception('ログインに失敗しました。再度お試しください');
    }
}

VerifyEmailControllerでメールアドレスを認証

最後にVerifyEmailControllerを新規作成し、以下のコードのように記述します。

VerifyEmailControllerでは

  • メールアドレス認証(email_verified_atにdatetimeを入力)
  • /email/verify/already-successまたは/email/verify/successにリダイレクト

をしています。

<?php
namespace App\Http\Controllers;

use Illuminate\Auth\Events\Verified;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use App\Models\User;

class VerifyEmailController extends Controller
{

    public function __invoke(Request $request): RedirectResponse
    {
        $user = User::find($request->route('id'));

        if ($user->hasVerifiedEmail()) {
            return redirect(env('FRONT_URL') . '/email/verify/already-success');
        }

        if ($user->markEmailAsVerified()) {
            event(new Verified($user));
        }

        return redirect(env('FRONT_URL') . '/email/verify/success');
    }
}

まとめ

この記事ではLaravelを使ったAPIサーバーでメールアドレス認証をする方法をご紹介しました。

メールアドレス認証を実装する手順は以下のとおりです。

  • UserモデルにMustVerifyEmailとHasApiTokensを実装
  • RegisterControllerで新規登録後にアクセストークンを作成
  • メールアドレス認証ルーティング
  • VerifyEmailControllerでメールアドレスを認証

Laravel5.7から新たに実装されたMustVerifyEmailインターフェースを実装することでメール送信工程が省けるたりしてメールアドレス認証機能がお手軽に作れます。

タイトルとURLをコピーしました