Gratis update & dukungan instalasi

Tutorial Website 28 Oct 2026

Cara Membuat Fitur Lupa Password di Laravel: Reset Password via Email yang Aman (Panduan 2026)

R Oleh renz mobellgnd
Cara Membuat Fitur Lupa Password di Laravel: Reset Password via Email yang Aman (Panduan 2026)

Cara Membuat Fitur Lupa Password di Laravel: Reset Password via Email yang Aman (Panduan 2026)

Fitur lupa password di Laravel dibuat dengan Password broker bawaan: pengguna memasukkan email, Laravel mengirim link reset bertoken ke email tersebut, lalu pengguna mengatur password baru lewat halaman reset. Anda tidak perlu Breeze atau Fortify; cukup route, controller, dan dua view Blade, plus konfigurasi email yang benar.

Panduan ini mengikuti dokumentasi resmi Laravel 12, ditambah bagian yang paling sering dilewati tutorial lain: anti user-enumeration, throttle, masa berlaku token, antrean email, pengujian, dan troubleshooting saat email tidak sampai.

Apa itu Password broker di Laravel?

Password broker mengurus seluruh logika reset password: membuat token, menyimpannya dalam bentuk hash di tabel password_reset_tokens, mengirim notifikasi email, lalu memvalidasi token saat pengguna mengirim password baru. Anda tidak perlu menulis logika token sendiri — dan itu justru poin keamanannya, karena token buatan sendiri rawan ditebak, tidak kedaluwarsa, atau tersimpan dalam bentuk teks biasa.

Tahap Yang terjadi
1. Minta linkPengguna mengisi email di halaman lupa password
2. Kirim emailLaravel membuat token, menyimpannya ter-hash, dan mengirim link
3. Buka linkPengguna klik link dari email, masuk ke halaman reset
4. Password baruLaravel memvalidasi token, mengganti password, dan menonaktifkan token

Apa saja prasyaratnya?

  1. Proyek Laravel 11 atau 12 dengan tabel users dan kolom email yang unik.
  2. Model User memakai trait Notifiable dan CanResetPassword.
  3. Pengiriman email sudah jalan (SMTP atau layanan lain; di lokal bisa memakai Mailtrap atau driver log).
  4. Halaman login sudah ada, karena setelah reset berhasil pengguna diarahkan kembali ke sana.
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
use Notifiable, CanResetPassword;
}

Tabel password_reset_tokens sudah tersedia di migrasi bawaan Laravel modern. Bila proyek Anda dari versi lama dan tabelnya belum ada, buat migrasinya lalu jalankan php artisan migrate.

Bagaimana cara mengonfigurasi email dan masa berlaku token?

Atur pengirim email di .env:

MAIL_MAILER=smtp
MAIL_HOST=mail.domainanda.com
MAIL_PORT=587
MAIL_USERNAME=noreply@domainanda.com
MAIL_PASSWORD="password-mailbox-anda"
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=noreply@domainanda.com
MAIL_FROM_NAME="Nama Aplikasi Anda"

Lalu periksa config/auth.php pada bagian passwords. Nilai expire 60 berarti token berlaku 60 menit — sudah masuk akal untuk kebanyakan aplikasi. Nilai throttle 60 berarti pengguna yang sama hanya bisa meminta link baru sekali per 60 detik, perlindungan sederhana terhadap spam permintaan reset.

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

Bagaimana cara membuat route lupa password?

Tambahkan empat route ini di routes/web.php, semuanya dengan middleware guest karena hanya pengguna yang belum login yang boleh mereset password:

use App\Http\Controllers\Auth\ForgotPasswordController;
use App\Http\Controllers\Auth\ResetPasswordController;

Route::middleware('guest')->group(function () {
Route::get('/lupa-password', [ForgotPasswordController::class, 'showLinkRequestForm'])
->name('password.request');
Route::post('/lupa-password', [ForgotPasswordController::class, 'sendResetLinkEmail'])
->name('password.email');
Route::get('/reset-password/{token}', [ResetPasswordController::class, 'showResetForm'])
->name('password.reset');
Route::post('/reset-password', [ResetPasswordController::class, 'reset'])
->name('password.update');
});

Nama route ini mengikuti konvensi Laravel.

Bagaimana cara mengirim link reset password?

Controller pertama hanya memvalidasi email, lalu meminta broker mengirim link lewat Password::sendResetLink():

public function sendResetLinkEmail(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)]);
}

Kenapa pesannya harus selalu sama?

Jika aplikasi menjawab "email tidak ditemukan" untuk alamat yang belum terdaftar, penyerang bisa memanen daftar email pengguna Anda satu per satu. Praktik yang lebih aman: selalu tampilkan pesan yang sama, misalnya "Jika email tersebut terdaftar, link reset sudah kami kirimkan." Laravel tetap hanya mengirim email ke alamat yang benar-benar terdaftar, dan error pengiriman tetap tercatat di log aplikasi Anda.

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

return back()->with(
'status',
'Jika email tersebut terdaftar, link reset password sudah kami kirimkan.'
);

Bagaimana cara membatasi permintaan berulang?

Tambahkan throttle pada route pengiriman link — throttle:5,1 berarti maksimal 5 permintaan per menit per IP:

Route::post('/lupa-password', [ForgotPasswordController::class, 'sendResetLinkEmail'])
->middleware('throttle:5,1')
->name('password.email');

Bagaimana cara membuat halaman reset password?

Form lupa password hanya butuh satu input email plus tombol kirim. Halaman reset memakai token dari URL sebagai hidden input, ditambah email dan password baru dengan konfirmasi:

<form method="POST" action="{{ route('password.update') }}">
@csrf
<input type="hidden" name="token" value="{{ $token }}">
<input id="email" type="email" name="email" value="{{ $email ?? old('email') }}" required>
<input id="password" type="password" name="password" required>
<input id="password_confirmation" type="password" name="password_confirmation" required>
<button type="submit">Reset Password</button>
</form>

Controller resetnya memvalidasi token lewat broker, mengganti password dengan hash baru, memperbarui remember token, dan memicu event PasswordReset:

public function reset(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' => Hash::make($password)])
->setRememberToken(Str::random(60));
$user->save();
event(new PasswordReset($user));
}
);

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

Memperbarui remember token menonaktifkan semua sesi "ingat saya" lama. Bila ingin lebih ketat, tambahkan Auth::logoutOtherDevices($password) di dalam callback.

Bagaimana cara menyesuaikan email reset dan memakai antrean?

Ubah subjek dan isi email lewat ResetPassword::toMailUsing() di AppServiceProvider, agar email tidak terlihat seperti template generik:

ResetPassword::toMailUsing(function ($notifiable, $url) {
return (new MailMessage)
->subject('Reset Password Akun ' . config('app.name'))
->line('Anda menerima email ini karena ada permintaan reset password untuk akun Anda.')
->action('Reset Password', $url)
->line('Link ini berlaku selama 60 menit. Jika Anda tidak meminta reset ini, abaikan saja email ini.');
});

Agar pengiriman tidak memperlambat halaman, kirim lewat antrean dengan menambahkan ShouldQueue pada class notifikasi kustom Anda — pola yang sama dengan pengiriman email otomatis Laravel dengan queue. Jangan lupa menjalankan queue worker di produksi, karena email antrean yang tidak diproses terlihat persis seperti "email tidak terkirim" di mata pengguna.

Bagaimana cara menguji fitur ini?

Tulis satu feature test dengan Notification::fake(): kirim token dari notifikasi ke endpoint reset dan pastikan tidak ada error sesi. Tambahkan tiga kasus negatif: token salah, password tanpa konfirmasi, dan token kedaluwarsa — ketiganya harus gagal.

Kenapa email reset tidak sampai? (Troubleshooting)

Gejala Penyebab paling umum Perbaiki
Tidak ada email sama sekaliQueue worker tidak jalanJalankan queue:work atau ubah QUEUE_CONNECTION ke sync sementara
Email masuk spamMAIL_FROM_ADDRESS tanpa SPF/DKIMKirim dari domain sendiri dan lengkapi SPF, DKIM, dan DMARC
Link mengarah ke localhostAPP_URL masih http://localhostSet APP_URL ke domain produksi lalu php artisan config:clear
"Token tidak valid" padahal baru diklikPengguna meminta link dua kali; token lama hangusSarankan memakai link dari email terbaru
"Token kedaluwarsa"Melewati 60 menitPerpanjang expire di config/auth.php bila perlu
Error 500 saat kirimKredensial SMTP salah atau port diblokirCek storage/logs/laravel.log dan uji SMTP dari panel hosting

Di shared hosting, dua penyebab pertama paling sering: antrean tidak diproses dan APP_URL lupa diubah setelah deploy. Sebelum mengumumkan fitur ini, kirim satu permintaan reset sungguhan dari domain produksi dan klik linknya sampai tuntas.

Kapan cara ini tidak cocok?

  1. Pengguna tak punya akses ke email terdaftar. Sediakan jalur reset oleh admin dari dashboard dengan verifikasi identitas manual — jangan membuat pengecualian yang melewati token.
  2. Login memakai Google atau SSO saja. Akun dari login Google dengan Socialite tidak punya password lokal; halaman reset harus menjelaskan bahwa mereka cukup login lewat Google.
  3. Aplikasi mobile murni (API). Link web tidak nyaman di dalam aplikasi. Gunakan endpoint API atau kode OTP — misalnya lewat notifikasi WhatsApp otomatis — dengan masa berlaku yang jauh lebih pendek.
  4. Akun dengan peran sensitif. Pertimbangkan verifikasi tambahan untuk admin, dan atur peran sejak awal lewat sistem multi role dan permission agar reset password tidak menjadi jalan pintas eskalasi hak akses.

FAQ

Apakah fitur lupa password Laravel gratis dan tanpa paket tambahan?

Ya. Password broker, tabel token, dan notifikasi reset sudah termasuk di framework Laravel. Anda hanya membayar layanan pengiriman email yang dipakai.

Berapa lama link reset password Laravel berlaku?

Secara default 60 menit, diatur lewat expire di config/auth.php. Jangan terlalu panjang: link berumur berhari-hari memberi waktu lebih besar bila email pengguna bocor.

Apakah token reset password disimpan dalam bentuk teks biasa?

Tidak. Laravel menyimpan hash token di tabel password_reset_tokens. Token yang dikirim lewat email hanya bisa dicocokkan dengan hash tersebut, sehingga kebocoran database saja tidak cukup untuk memakai token.

Bisakah satu pengguna meminta banyak link reset sekaligus?

Bisa meminta, tetapi setiap permintaan baru menggantikan token sebelumnya, dan throttle membatasi permintaan berulang dalam 60 detik. Sarankan pengguna memakai link dari email terbaru.

Apakah pengguna yang sedang login bisa memakai halaman lupa password?

Seharusnya tidak. Semua route di panduan ini memakai middleware guest. Pengguna yang sudah login sebaiknya mengganti password lewat halaman profil, dengan verifikasi password lama.

Apakah reset password otomatis mengeluarkan pengguna dari perangkat lain?

Mengatur ulang remember token menonaktifkan login "ingat saya" di perangkat lain, tetapi sesi aktif yang sudah berjalan belum tentu langsung berakhir. Untuk pengamanan penuh, tambahkan Auth::logoutOtherDevices().

Apa bedanya reset password dengan "ganti password" di halaman profil?

Reset password dipakai saat pengguna tidak bisa login sama sekali, dan verifikasinya lewat kepemilikan email. Ganti password dipakai saat pengguna sudah login, dan verifikasinya lewat password lama plus sesi aktif. Keduanya harus ada, tetapi jangan saling menggantikan.

Penutup

Fitur lupa password yang baik terasa membosankan: pengguna memasukkan email, mengklik link, mengatur password baru, lalu kembali bekerja. Kebosanan itu justru tandanya benar.

Mulailah dari broker bawaan Laravel, kunci tiga hal — pesan yang seragam, throttle, dan masa berlaku token — lalu uji sebelum naik ke produksi. Bila Anda membangun aplikasi dari source code yang sudah jadi, periksa apakah fitur ini sudah ada dan apakah ketiga kunci itu sudah diterapkan.