Autentikasi
Laravel memisahkan "bagaimana pengguna dikenali" (guard) dari "di mana datanya" (provider). Memahami pemisahan ini membuat autentikasi web, API, dan admin bisa hidup berdampingan tanpa saling mengganggu.
Intisari
- Guard = cara mengenali pengguna per permintaan. Provider = dari mana datanya diambil.
- Default: guard
web(session + cookie) dan providerusers(Eloquent). Auth::attempt()memverifikasi kredensial; wajib diikutisession()->regenerate().- Untuk API, guard-nya
sanctumโ tanpa session, tanpa cookie. - Jangan menulis sendiri logika login, reset password, dan verifikasi email. Pakai starter kit atau Fortify.
Dua konsep, empat baris konfigurasi
// config/auth.php
'guards' => [
'web' => ['driver' => 'session', 'provider' => 'users'],
'sanctum' => ['driver' => 'sanctum', 'provider' => 'users'],
'admin' => ['driver' => 'session', 'provider' => 'admins'],
],
'providers' => [
'users' => ['driver' => 'eloquent', 'model' => App\Models\User::class],
'admins' => ['driver' => 'eloquent', 'model' => App\Models\Admin::class],
],
auth()->user(); // guard default (web)
auth('admin')->user(); // guard lain
auth('sanctum')->user();
Route::middleware('auth:admin')->group(...);
Ini sumber kebingungan yang khas. Kamu login sebagai admin, lalu auth()->user() di
suatu controller mengembalikan null โ karena baris itu memakai guard web, sementara
sesi adminmu ada di guard admin. Kalau aplikasimu punya lebih dari satu guard, selalu
sebutkan guard-nya, atau pakai $request->user() yang mengambil dari guard yang
memvalidasi permintaan itu.
Login manual, kalau memang perlu
public function store(LoginRequest $request): RedirectResponse
{
$kredensial = $request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
if (! Auth::attempt($kredensial, $request->boolean('ingat_saya'))) {
return back()->withErrors([
'email' => 'Email atau kata sandi salah.', // JANGAN bedakan keduanya
])->onlyInput('email');
}
$request->session()->regenerate(); // WAJIB โ cegah session fixation
return redirect()->intended(route('dasbor'));
}
public function destroy(Request $request): RedirectResponse
{
Auth::logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect('/');
}
| Baris | Kalau dilewati |
|---|---|
session()->regenerate() | Session fixation: penyerang yang bisa menetapkan ID sesi korban sebelum login akan ikut terautentikasi |
| Pesan error yang sama untuk email dan password | User enumeration: penyerang bisa memetakan email mana yang terdaftar |
session()->invalidate() saat logout | Data sesi lama tetap hidup |
regenerateToken() | Token CSRF lama masih berlaku |
Method yang sering dipakai
Auth::check(); // sudah login?
Auth::id(); // ID tanpa memuat model
Auth::login($user); // login tanpa password (mis. setelah registrasi)
Auth::loginUsingId(3);
Auth::once($kredensial); // verifikasi tanpa membuat sesi
Auth::logoutOtherDevices($password); // akhiri sesi di perangkat lain
Auth::id() lebih murah daripada Auth::user()->id. Yang pertama membaca
ID dari sesi; yang kedua memuat seluruh baris pengguna dari database. Di halaman yang cuma perlu tahu
"siapa ini" untuk sebuah kunci cache, perbedaannya adalah satu query per permintaan.
Session: di mana disimpan menentukan skalabilitas
| Driver session | Berbagi antar kontainer? | Catatan |
|---|---|---|
file | Tidak | Pengguna ter-logout acak saat load balancer memindahkannya |
cookie | Ya (di sisi klien) | Terbatas 4 KB, terenkripsi; hindari data besar |
database | Ya | Satu query tulis per permintaan |
redis | Ya | Pilihan produksi โ cepat dan punya TTL bawaan |
Gejala klasik "kadang ter-logout sendiri". Session driver file di belakang load balancer:
sesi dibuat di kontainer A, permintaan berikutnya masuk ke kontainer B yang tidak punya berkasnya. Solusinya
bukan sticky session di load balancer, melainkan memindahkan session ke Redis. Sticky session membuat
penyeimbangan beban jadi timpang dan menyulitkan deploy.
Jangan menulis sendiri
| Kebutuhan | Pakai |
|---|---|
| Login, registrasi, reset password, verifikasi email | Starter kit (materi berikutnya) atau Fortify |
| Autentikasi dua faktor | Fortify |
| Login lewat Google/GitHub | Socialite |
| Token API | Sanctum |
| OAuth2 sebagai penyedia | Passport โ hanya kalau kamu benar-benar server OAuth2 |
Alur reset password yang aman punya lebih banyak detail daripada yang terlihat: token sekali pakai, masa berlaku, pembatasan laju, dan pesan yang tidak membocorkan keberadaan email. Semuanya sudah selesai dan sudah teruji di paket resmi.
Latihan: buat halaman login manual dengan potongan kode di atas, lalu sengaja hapus baris
session()->regenerate(). Perhatikan nilai cookie laravel_session di DevTools sebelum
dan sesudah login โ kalau nilainya tidak berubah, itulah lubang session fixation yang baru saja kamu buat.
Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.