Implementasi Email Verification dan Custom Password Reset di Laravel

By Samsul Arifin October 26, 2024 08:30 AM
Implementasi Email Verification dan Custom Password Reset di Laravel

Berikut adalah tutorial lengkap untuk Email Verification dan Custom Password Reset di Laravel. Namun sebelum ke tutorlal ini, ada baiknya mengikuti tutorial sebelumnya 

Persiapan Awal

- Laravel versi terbaru (Laravel 10) harus sudah diinstal.

- Database sudah dikonfigurasi di .env dan tabel sudah dimigrasi.

- Laravel Breeze untuk scaffolding autentikasi juga disarankan. Jika belum, jalankan:

composer require laravel/breeze --dev 
php artisan breeze:install 
php artisan migrate

Langkah 1: Mengaktifkan Verifikasi Email

1.1 Mengaktifkan Middleware Verifikasi Email

Untuk data user, kita akan pakai data sebelumnya pada tutorial Membuat Multi-Authentication System di Laravel Login Admin dan User. Silahkan mengikuti tutorial sebelumnya untuk detailnya

Tambahkan middleware verified pada route yang ingin dilindungi. Buka routes/web.php:

use Illuminate\Support\Facades\Route;

Route::middleware(['auth', 'verified','role:user'])->group(function () {
    Route::get('/user/dashboard', function () {
        return view('user.dashboard');
    })->name('user.dashboard');
});

Hal ini akan melakukan verifikasi setiap melakukan login yang dikirim ke email.  

1.2 Mengaktifkan Fitur Verifikasi di Model User

Di file app/Models/User.php, implementasikan MustVerifyEmail:

use Illuminate\Contracts\Auth\MustVerifyEmail;

class User extends Authenticatable implements MustVerifyEmail
{
    // Konfigurasi verifikasi email siap digunakan
}

1.3 Menyesuaikan View Verifikasi Email

Jika ingin mengubah tampilan, buat resources/views/auth/verify-email.blade.php:

@extends('layouts.app')

@section('content')
<div>
    <h1>Email Verification</h1>
    <p>Check your email to verify your account.</p>

    @if (session('status') == 'verification-link-sent')
        <p>A new verification link has been sent to your email address.</p>
    @endif

    <form method="POST" action="{{ route('verification.send') }}">
        @csrf
        <button type="submit">Resend Verification Email</button>
    </form>
</div>
@endsection

1.4 Pengujian Verifikasi Email

Setelah pendaftaran, pengguna akan diminta verifikasi email dan diarahkan ke halaman tersebut. Verifikasi akun dengan mengklik link pada email. 

Kita akan menggunakan https://mailtrap.io untuk konfigurasi SMTP mailer nya. jika belum registrasi, silahkan registrasi dan login ke akun mailtrap. Setelah login, buka menu INBOXES lalu ada SMTP untuk kita lakukan testing seperti berikut:

Setelah dapat, edit file .env di laravel menjadi sebagai berikut:

MAIL_MAILER=smtp
MAIL_HOST=sandbox.smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=304a002842dcf4
MAIL_PASSWORD=********6a30

Sesuaikan config SMTP dengan config SMTP di mailtrap anda. Setelah itu kita akan testing login menggunakan URL berikut:

http://localhost:8000/login

Setelah itu akan muncul verifikasi sebagai sebagai berikut:

Cek di inbox mailtrap, dan akan menghasilkan seperti berikut:

Langkah 2: Mengatur Custom Password Reset

2.1 Membuat Notifikasi Reset Password

Buka file app/Notifications/ResetPasswordNotification.php atau jika belum ada, bisa dibuat dengan:

php artisan make:notification ResetPasswordNotification

Edit ResetPasswordNotification.php untuk menyesuaikan isi email:

namespace App\Notifications;

use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\MailMessage;

class ResetPasswordNotification extends Notification
{
    public $token;

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

    public function via(object $notifiable): array
    {
        return ['mail'];
    }

    public function toMail($notifiable)
    {
        return (new MailMessage)
                    ->subject('Reset Your Password')
                    ->line('You are receiving this email because we received a password reset request for your account.')
                    ->action('Reset Password', url(route('password.reset', $this->token, false)))
                    ->line('If you did not request a password reset, no further action is required.');
    }
}

2.2 Update Model User untuk menggunakan Notifikasi

Di app/Models/User.php, tambahkan method sendPasswordResetNotification:

use App\Notifications\ResetPasswordNotification;

public function sendPasswordResetNotification($token)
{
    $this->notify(new ResetPasswordNotification($token));
}

2.3 Membuat Route dan View untuk Password Reset

Tambahkan route untuk mengelola password reset di routes/web.php:

use Illuminate\Support\Facades\Password;
use Illuminate\Http\Request;

Route::get('/forgot-password', function () {
    return view('auth.forgot-password');
})->middleware('guest')->name('password.request');

Route::post('/forgot-password', function (Request $request) {
    $request->validate(['email' => 'required|email']);
    
    $status = Password::sendResetLink(
        $request->only('email')
    );

    return $status === Password::RESET_LINK_SENT
                ? back()->with(['status' => __($status)])
                : back()->withErrors(['email' => __($status)]);
})->middleware('guest')->name('password.email');

Route::get('/reset-password/{token}', function ($token) {
    return view('auth.reset-password', ['token' => $token]);
})->middleware('guest')->name('password.reset');

Route::post('/reset-password', function (Request $request) {
    $request->validate([
        'token' => 'required',
        'email' => 'required|email',
        'password' => 'required|min:8|confirmed',
    ]);

    $status = Password::reset(
        $request->only('email', 'password', 'password_confirmation', 'token'),
        function ($user, $password) {
            $user->forceFill([
                'password' => bcrypt($password)
            ])->save();
        }
    );

    return $status === Password::PASSWORD_RESET
                ? redirect()->route('login')->with('status', __($status))
                : back()->withErrors(['email' => [__($status)]]);
})->middleware('guest')->name('password.update');

2.4 Membuat View untuk Password Reset

Forgot Password View (resources/views/auth/forgot-password.blade.php)

@extends('layout')

@section('content')
<h1>Forgot Password</h1>
<form action="{{ route('password.email') }}" method="POST">
    @csrf
    <div class="mb-3">
        <label for="email" class="form-label">Email:</label>
        <input type="email" class="form-control" id="email" name="email" required>
        <div id="emailHelp" class="form-text">We'll never share your email with anyone else.</div>
        <button type="submit" class="btn btn-primary mt-50">Send Password Reset Link</button>
    </div>
</form>
@endsection

Reset Password View (resources/views/auth/reset-password.blade.php)

@extends('layout')

@section('content')
<h1>Reset Password</h1>
<form action="{{ route('password.update') }}" method="POST">
    @csrf
    <div class="mb-3">
        <input type="hidden" name="token" value="{{ $request->route('token') }}">
        <label for="email">Email:</label>
        <input type="email" id="email" class="form-control" name="email" required>
    </div>
    <div class="mb-3">
        <label for="password">New Password:</label>
        <input type="password" id="password" class="form-control" name="password" required>
    </div>
    <div class="mb-3">
        <label for="password_confirmation">Confirm Password:</label>
        <input type="password" id="password_confirmation" class="form-control" name="password_confirmation" required>
    </div>
    <button type="submit" class="btn btn-primary">Reset Password</button>
</form>
@endsection

Silahkan testing dengan akses URL login kemudian klik Forgot your password? hasilnya seperti berikut:

​​​​​​Jika berhasil, maka akan tampil seperti berikut di inboxes mailtrap:

Setelah klik Reset Password, akan diarahkan ke halaman change password berikut:

Bagikan Artikel: