โ† Semua pembelajaran / Laravel Nol โ†’ Enterprise
Fase 4 ยท Autentikasi & Keamanan

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.

Sumber asli laravel.com Resmi Rangkuman ~7 menit baca

Intisari

  • Guard = cara mengenali pengguna per permintaan. Provider = dari mana datanya diambil.
  • Default: guard web (session + cookie) dan provider users (Eloquent).
  • Auth::attempt() memverifikasi kredensial; wajib diikuti session()->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('/');
}
BarisKalau dilewati
session()->regenerate()Session fixation: penyerang yang bisa menetapkan ID sesi korban sebelum login akan ikut terautentikasi
Pesan error yang sama untuk email dan passwordUser enumeration: penyerang bisa memetakan email mana yang terdaftar
session()->invalidate() saat logoutData 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 sessionBerbagi antar kontainer?Catatan
fileTidakPengguna ter-logout acak saat load balancer memindahkannya
cookieYa (di sisi klien)Terbatas 4 KB, terenkripsi; hindari data besar
databaseYaSatu query tulis per permintaan
redisYaPilihan 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

KebutuhanPakai
Login, registrasi, reset password, verifikasi emailStarter kit (materi berikutnya) atau Fortify
Autentikasi dua faktorFortify
Login lewat Google/GitHubSocialite
Token APISanctum
OAuth2 sebagai penyediaPassport โ€” 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.