Autentikasi menjawab pertanyaan "siapa kamu?", sedangkan otorisasi menjawab "apa yang boleh kamu lakukan?". Kesalahan di area ini adalah penyebab kebocoran data yang paling mahal. Untungnya, Laravel menyediakan fondasi yang aman. Tugasmu: memahami alurnya dan tidak merusaknya.
Gambaran besar: apa yang terjadi saat login
- Pengguna mengirim email dan password lewat form.
- Laravel mencari pengguna dengan email itu dan membandingkan password dengan hash yang tersimpan.
- Jika cocok, Laravel membuat session dan menyimpan ID pengguna di dalamnya.
- Browser menerima cookie session (terenkripsi). Pada permintaan berikutnya cookie itu dikirim, sehingga Laravel tahu siapa pengguna tersebut.
- Middleware
authmemeriksa keberadaan session ini sebelum mengizinkan akses halaman terlindungi.
Pilihan: pakai starter kit atau buat sendiri?
| Opsi | Cocok untuk |
|---|---|
| Laravel Breeze | Paling sederhana: login, registrasi, reset password, verifikasi email, profil. Cocok untuk kebanyakan proyek dan untuk belajar membaca kodenya |
| Jetstream | Fitur lengkap: 2FA, manajemen tim, sesi browser, API token |
| Fortify | Backend autentikasi tanpa tampilan (headless), kamu buat UI sendiri |
| Sanctum | Token untuk SPA dan API/mobile |
| Manual | Untuk memahami konsepnya atau kebutuhan sangat khusus |
Rekomendasi: pasang Breeze lalu baca kode yang dihasilkan.
composer require laravel/breeze --dev
php artisan breeze:install blade
php artisan migrate
Anatomi login manual
Walau starter kit menyediakannya, memahami intinya penting:
public function login(Request $request)
{
$credentials = $request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
if (Auth::attempt($credentials, $request->boolean('remember'))) {
$request->session()->regenerate(); // cegah session fixation
return redirect()->intended('/dashboard');
}
return back()->withErrors([
'email' => 'Email atau kata sandi salah.', // pesan seragam
])->onlyInput('email');
}
Hal-hal yang penting:
Auth::attempt()mencari user berdasarkan email, lalu memverifikasi password denganHash::check(). Kamu tidak membandingkan password manual.session()->regenerate()mengganti ID session setelah login untuk mencegah session fixation.intended()mengembalikan pengguna ke halaman yang semula ingin ia buka.- Pesan error sengaja seragam. Jangan membedakan "email tidak ditemukan" dan "password salah", karena itu membantu penyerang menebak email terdaftar (user enumeration).
Menyimpan password dengan benar
Tidak pernah menyimpan password asli. Simpan hash satu arah yang sengaja lambat:
$user->password = Hash::make($request->password); // bcrypt (default) atau argon2id
Atau cukup beri cast 'password' => 'hashed' di model (Laravel 10+). Konfigurasi algoritma ada di config/hashing.php. Hash memakai salt acak sehingga dua password yang sama menghasilkan hash berbeda, dan bcrypt/argon2 dirancang agar sulit di-brute force.
Aturan password yang masuk akal (sejalan dengan panduan NIST): panjang lebih penting daripada kerumitan. Minimal 8 (lebih baik 12) karakter, cek terhadap daftar password bocor:
use Illuminate\Validation\Rules\Password;
'password' => ['required', 'confirmed', Password::min(8)->letters()->numbers()->uncompromised()],
uncompromised() memeriksa password ke basis data kebocoran publik tanpa mengirim password aslinya.
Melindungi route dengan middleware
Route::middleware('auth')->group(function () {
Route::get('/dashboard', DashboardController::class);
});
Route::middleware('guest')->group(function () {
Route::get('/login', ...); // pengguna yang sudah login dialihkan
});
Cara kerja middleware dijelaskan di Mengenal Middleware pada Laravel. Dalam kode Blade: @auth ... @endauth dan @guest ... @endguest.
Guard dan provider
Guard menentukan cara pengguna diautentikasi per permintaan (session untuk web, token untuk API). Provider menentukan dari mana data pengguna diambil (Eloquent model User, atau tabel admins). Dengan keduanya kamu bisa membuat autentikasi terpisah untuk pelanggan dan admin:
Auth::guard('admin')->attempt($credentials);
Konfigurasinya ada di config/auth.php.
Reset password
Alur yang benar memakai token sekali pakai yang dikirim lewat email:
- Pengguna memasukkan email → sistem membuat token acak, menyimpan hash-nya dengan waktu pembuatan, dan mengirim tautan.
- Tautan membawa token; pengguna membuat password baru.
- Token divalidasi (belum kedaluwarsa, cocok dengan hash), password diperbarui, token dihapus.
Prinsip penting: jangan pernah mengirim password lewat email atau mengganti password pengguna sebelum ia mengonfirmasi lewat tautan, karena itu membuat siapa pun bisa mengunci akun orang lain. Respons "tautan dikirim jika email terdaftar" harus sama untuk email yang ada maupun tidak ada. Laravel menyediakan semuanya lewat Password::sendResetLink() dan Password::reset().
Verifikasi email
Implementasikan interface MustVerifyEmail pada model User, lalu tambahkan middleware verified pada route yang butuh email terverifikasi. Laravel mengirim tautan bertanda tangan (signed URL) yang tidak bisa dipalsukan.
Melindungi dari brute force
Tanpa pembatasan, penyerang bisa mencoba ribuan password. Gunakan RateLimiter:
$key = Str::lower($request->email).'|'.$request->ip();
if (RateLimiter::tooManyAttempts($key, 5)) {
$detik = RateLimiter::availableIn($key);
throw ValidationException::withMessages([
'email' => "Terlalu banyak percobaan. Coba lagi dalam {$detik} detik.",
]);
}
// gagal login: RateLimiter::hit($key, 60);
// berhasil: RateLimiter::clear($key);
Breeze sudah menyertakan pola ini.
Otorisasi: gate dan policy
Setelah tahu siapa penggunanya, tentukan haknya:
// app/Policies/PostPolicy.php
public function update(User $user, Post $post): bool
{
return $user->id === $post->user_id;
}
// di controller
$this->authorize('update', $post);
Selalu periksa kepemilikan data di sisi server. Pengguna yang bisa mengganti /posts/7/edit menjadi /posts/8/edit dan mengakses data orang lain adalah kerentanan IDOR yang sangat umum.
Daftar periksa keamanan
- [ ] Password di-hash (bcrypt/argon2), tidak pernah disimpan atau dikirim polos.
- [ ] HTTPS aktif di produksi; cookie
securedanhttp_only. - [ ]
session()->regenerate()setelah login,invalidate()+regenerateToken()saat logout. - [ ] Pembatasan laju untuk login, registrasi, dan reset password.
- [ ] Pesan error tidak membocorkan keberadaan akun.
- [ ] Token reset sekali pakai dan kedaluwarsa (misalnya 60 menit).
- [ ] CSRF aktif (
@csrf) pada semua form POST. - [ ] Otorisasi diperiksa di server untuk setiap data milik pengguna.
- [ ] Pertimbangkan 2FA untuk akun admin.
- [ ] Pencatatan log login dan perubahan penting (tanpa mencatat password).
Kesalahan yang sering terjadi
| Kesalahan | Akibat |
|---|---|
Membandingkan password dengan == | Tidak cocok karena yang tersimpan adalah hash; gunakan Hash::check |
| Menonaktifkan CSRF "supaya mudah" | Terbuka terhadap pemalsuan permintaan |
| Menyimpan token/ rahasia di repo | Kebocoran kredensial |
| Mengandalkan menyembunyikan tombol di UI | Server tetap bisa diakses langsung; periksa di backend |
| Membuat sistem login sendiri tanpa memahami celahnya | Rawan; gunakan komponen yang sudah teruji |
Kesimpulan
Autentikasi yang aman bertumpu pada hash password yang kuat, session yang dikelola benar, pembatasan percobaan login, alur reset berbasis token, dan otorisasi di setiap akses data. Gunakan starter kit Laravel, pahami setiap langkahnya, dan jangan mengganti mekanisme keamanannya dengan jalan pintas.
Komentar (0)
Masuk / Daftar