Hari ini saya masuk ke materi yang paling sering ditanya orang saat pertama belajar Laravel: authentication. Selama ini saya cuma tahu login itu “masukin email dan password, terus masuk”. Ternyata di balik itu ada konsep yang menarik: guard, provider, sampai cara Laravel menyimpan password dengan aman. Jujur, agak pusing di awal — tapi setelah saya bedah pelan-pelan, polanya masuk akal.
Autentikasi itu soal “membuktikan siapa kamu”
Saya suka mengibaratkan autentikasi seperti masuk ke kantor. Kamu datang ke lobby, tunjukkan kartu identitas (email + password), lalu satpam memverifikasi datamu ke database karyawan. Kalau cocok, kamu diberi “tanda pengenal” untuk dipakai selama di dalam gedung — di Laravel, tanda pengenal itu disimpan di session (kalau pakai web) atau dikirim sebagai token (kalau API). Ini berarti autentikasi sebenarnya dua langkah: verifikasi identitas lalu menjaga identitas itu tetap dikenali di request berikutnya.
Guard dan Provider: pasangan yang wajib dipahami
Dua istilah ini yang bikin saya bingung paling lama. Sekarang saya catat begini:
- Guard = cara menentukan bagaimana pengguna dibuktikan dan disimpan di tiap request. Guard
webmemakai session + cookie; guardsanctummemakai token untuk API. - Provider = sumber data identitasnya, yaitu dari mana pengguna diambil. Default: tabel
userslewat modelApp\Models\User.
Di file config/auth.php, Laravel memetakan keduanya. Jadi kalau suatu saat aplikasi saya pakai login dari tabel admin atau API eksternal, saya cukup ganti provider-nya — guard-nya bisa tetap sama. Buat saya yang baru belajar, ini artinya framework-nya memang didesain untuk diganti-ganti bagiannya tanpa membongkar semuanya.
Jenis Guard: kapan pakai yang mana
Setelah saya pelajari lebih lanjut, ternyata ada beberapa tipe guard yang harus saya pahami kapan dipakainya:
- web guard — guard default untuk aplikasi biasa yang diakses lewat browser. Menggunakan session dan cookie untuk menjaga identitas pengguna tetap aktif. Ini yang saya pakai di sebagian besar proyek belajar saya.
- api guard — guard untuk endpoint API yang tidak stateful. Biasanya memakai token di header
Authorization: Bearer {token}. Cocok untuk integrasi antar aplikasi. - sanctum guard — campuran antara web dan api. Sanctum bisa menghasilkan personal access token untuk mobile app, sekaligus bisa memakai cookie-based auth untuk SPA. Ini guard yang saya rekomendasikan untuk proyek yang punya frontend JavaScript terpisah.
Kenapa password tidak pernah disimpan “polos”
Sebelumnya saya sempat mikir: “kenapa tidak simpan password apa adanya saja?” Lalu saya sadar — kalau database bocor, semua password user langsung terbaca. Solusinya: simpan hash, hasil satu arah dari password. Hash tidak bisa dibalik jadi password asli, tapi bisa dicek ulang: hash(password yang dimasukkan) dibandingkan dengan hash di database.
Di Laravel cukup pakai facade Hash. Default algoritmanya bcrypt, dan secara berkala Laravel bisa “meng-upgrade” hash ke algoritma yang lebih kuat saat user login (fitur needsRehash). Saya baru paham sekarang kenapa artikel-artikel selalu bilang “jangan pernah simpan password plaintext”. Ini yang saya catat:
use Illuminate\Support\Facades\Hash;
// Menyimpan password saat registrasi
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
// Mengecek password saat login
if (Hash::check($request->password, $user->password)) {
// password benar
}Perhatikan: tidak ada satu pun kode di atas yang pernah melihat isi password aslinya setelah disimpan. Hash::make menghasilkan string acak yang berbeda tiap kali — jadi dua user dengan password sama tetap punya hash berbeda. Itu justru bagus, kata saya, karena menyulitkan penyerang yang memakai daftar hash umum.
Breeze: scaffolding login/register yang siap pakai
Kalau “membangun dari nol” terasa berat, Laravel punya paket resmi bernama Breeze — semacam kerangka awal login, register, lupa password, dan verifikasi email, lengkap dengan halaman Blade-nya. Saya sendiri merasa ini cara tercepat untuk melihat bentuk asli auth Laravel tanpa menulis semuanya manual:
composer require laravel/breeze --dev php artisan breeze:install blade php artisan migrate npm install && npm run dev
Setelah itu route /login, /register, dan /dashboard langsung tersedia. Breeze bukan satu-satunya pilihan — ada Jetstream yang lebih lengkap (two-factor authentication, team) — tapi untuk belajar, Breeze lebih ramah karena kodenya minim dan mudah dibaca. Ini berarti bagi saya: sebelum saya paham auth dari nol, saya bisa pelajari implementasi resmi yang sudah benar, lalu memodifikasinya.
Breeze vs Jetstream vs Fortify: mana yang cocok?
Pertanyaan ini sempat mengganjal di kepala saya. Ketiganya punya fungsi serupa tapi tingkatannya berbeda. Saya buat tabel perbandingan supaya lebih jelas:
| Fitur | Breeze | Jetstream | Fortify |
|---|---|---|---|
| Login / Register / Reset Password | Ya | Ya | Ya |
| Two-Factor Authentication | Tidak | Ya (Livewire / Inertia) | Ya (tersedia) |
| Team Management | Tidak | Ya | Tidak |
| Profile Update / Delete | Dasar | Lengkap | Dapat dikustomisasi |
| Email Verification | Ya | Ya | Ya |
| Kapan pakai | Belajar, prototipe cepat | Produksi dengan fitur lengkap | Butuh auth logic tanpa view |
Simpulan saya: mulai dari Breeze saat belajar. Pindah ke Jetstream kalau proyek butuh fitur lengkap seperti 2FA dan team. Pakai Fortify kalau hanya butuh backend auth tanpa scaffold view — misalnya untuk API-only project atau kalau mau bikin halaman login sendiri dari nol.
Remember Me dan Session Management
Saya perhatikan di banyak website ada checkbox “Ingat saya” saat login. Di Laravel, ini ternyata sangat sederhana — cukup kirim parameter kedua ke Auth::attempt sebagai boolean. Ketika $remember bernilai true, Laravel akan menyimpan cookie jangka panjang (default 5 tahun) di browser pengguna, sehingga session tidak expired saat browser ditutup.
$credentials = $request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
$remember = $request->boolean('remember');
if (Auth::attempt($credentials, $remember)) {
$request->session()->regenerate();
return redirect()->intended('/dashboard');
}Sementara itu, untuk logout dan invalidasi session, saya catat langkah-langkah ini:
use Illuminate\Support\Facades\Auth;
// Logout + invalidasi session + revoke remember token
Auth::logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect('/');Saya belajar bahwa invalidate() menghapus session lama dan regenerateToken() memperbarui CSRF token. Tanpa keduanya, ada risiko session fixation di mana penyerang bisa mengaitkan session ID miliknya ke akun korban.
Password Reset: dari request sampai email
Fitur lupa password yang kita lihat di website sehari-hari sebenarnya mengikuti alur yang sangat terstruktur. Saya coba rangkum step-by-step supaya mudah diingat:
- User request reset — mengisi email di form
/forgot-password. Laravel mencari user berdasarkan email di database. - Token dibuat — Laravel menggunakan
Broker(viaPassword::broker()) untuk membuat token unik dan menyimpannya di tabelpassword_reset_tokens. - Email dikirim — Laravel mengirim email berisi link reset yang mengandung token. Link ini berlaku terbatas waktu (default 60 menit).
- User mengisi password baru — setelah klik link, user diarahkan ke form
/reset-password/{token}. Ketika submit, Laravel memverifikasi token + email, lalu meng-update password dengan hash baru.
Yang menarik bagi saya: semua alur ini sudah tersedia secara built-in kalau pakai Breeze. Tapi kalau ingin kustomisasi — misalnya menambahkan captcha atau mengubah format email — saya tinggal override method di model User atau publish view-nya dengan php artisan vendor:publish --tag=laravel-mail.
Two-Factor Authentication dengan Fortify
Two-Factor Authentication (2FA) menambahkan lapisan keamanan ekstra: selain password, user juga harus memasukkan kode dari aplikasi authenticator seperti Google Authenticator. Awalnya saya pikir ini sangat rumit, ternyata Laravel sudah menyediakan dukungan siap pakai lewat Fortify.
// Di config/fortify.php, aktifkan 2FA:
'features' => [
Features::registration(),
Features::resetPasswords(),
Features::emailVerification(),
Features::updateProfileInformation(),
Features::updatePasswords(),
Features::twoFactorAuthentication([
'confirm' => true,
]),
],Saat user mengaktifkan 2FA, Fortify akan menampilkan QR code yang dipindai dengan aplikasi authenticator. Setelah itu, setiap login akan meminta kode 6 digit tambahan. Di database, Laravel menyimpan secret key 2FA di kolom two_factor_secret pada tabel users. Bagi saya, ini contoh bagaimana fitur keamanan canggih bisa diimplementasikan dengan konfigurasi minimal kalau framework-nya sudah mendukung.
Social Login: Google OAuth dengan Laravel Socialite
Banyak aplikasi modern menyediakan opsi “Login dengan Google”. Laravel memfasilitasi ini lewat paket Socialite. Prosesnya: user dikirim ke Google, Google memverifikasi identitas, lalu mengirim kembali ke aplikasi kita dengan informasi user (email, nama, foto).
composer require laravel/socialite
// config/services.php
'google' => [
'client_id' => env('GOOGLE_CLIENT_ID'),
'client_secret' => env('GOOGLE_CLIENT_SECRET'),
'redirect' => env('GOOGLE_REDIRECT_URI'),
],
// routes/web.php
Route::get('/auth/google', [GoogleController::class, 'redirect']);
Route::get('/auth/google/callback', [GoogleController::class, 'callback']);
// GoogleController.php
use Laravel\Socialite\Facades\Socialite;
public function redirect()
{
return Socialite::driver('google')->redirect();
}
public function callback()
{
$googleUser = Socialite::driver('google')->user();
// Cari atau buat user berdasarkan email Google
$user = User::firstOrCreate(
['email' => $googleUser->getEmail()],
[
'name' => $googleUser->getName(),
'password' => Hash::make( Str::random(32) ),
]
);
Auth::login($user);
return redirect('/dashboard');
}Catatan penting: untuk password di user social login, saya harus tetap mengisi field password karena database mungkin mengharuskannya. Solusinya adalah memberi password acak dengan Str::random(32) — user tidak akan pernah memakainya karena login lewat Google. Ini solusi sederhana yang saya temukan dari banyak tutorial, dan ternyata memang cara yang umum dipakai.
Middleware Auth: penjaga gerbang setelah login
Setelah login berhasil, pertanyaannya: bagaimana cara memastikan hanya user yang sudah login yang bisa mengakses halaman tertentu? Jawabannya: middleware. Di Laravel, middleware auth bekerja seperti penjaga gerbang di tiap route — memeriksa apakah user sudah terautentikasi sebelum request diteruskan ke controller.
| Middleware | Fungsi | Kapan dipakai |
|---|---|---|
auth | Mengecek apakah user sudah login. Jika tidak, redirect ke halaman login. | Semua halaman yang butuh user terautentikasi: dashboard, profil, settings. |
guest | Kebalikan dari auth — hanya bisa diakses user yang belum login. | Halaman login, register, lupa password. Agar user yang sudah login tidak melihat form login lagi. |
auth:sanctum | Mengecek token Sanctum untuk request API. | Endpoint API yang butuh autentikasi token. |
throttle:api | Rate limiting untuk request API. | Semua endpoint API untuk mencegah abuse. |
// routes/web.php
Route::middleware('auth')->group(function () {
Route::get('/dashboard', [DashboardController::class, 'index']);
Route::get('/profile', [ProfileController::class, 'show']);
});
// Hanya tamu yang boleh akses
Route::middleware('guest')->group(function () {
Route::get('/login', [LoginController::class, 'showForm']);
Route::get('/register', [RegisterController::class, 'showForm']);
});
// API routes pakai sanctum
Route::middleware('auth:sanctum')->apiResource('posts', PostController::class);Saya juga baru paham bahwa middleware bisa dikustomisasi. Misalnya, saya bisa membuat middleware sendiri untuk mengecek apakah user adalah admin sebelum mengakses halaman manajemen. Ini memungkinkan saya mengontrol akses di tingkat route tanpa perlu mengecek role di setiap method controller.
Perbandingan Metode Autentikasi
Sebelum saya lanjut, saya ingin merangkum berbagai metode autentikasi yang tersedia di Laravel dalam satu tabel. Ini membantu saya menentukan pendekatan mana yang tepat untuk setiap situasi:
| Metode | Cara Kerja | Cocok Untuk | Contoh Header |
|---|---|---|---|
| Session | Cookie-based, stateful di server | Web app, Blade + Breeze/Jetstream | Cookie otomatis |
| Personal Access Token | Token statis dibuat user, dikirim di header | Mobile app, CLI tools | Authorization: Bearer {token} |
| API Token (Sanctum SPA) | Cookie-based untuk SPA, stateful | SPA (Vue, React) di domain sama | Cookie otomatis + CSRF |
| Laravel Passport (OAuth2) | Full OAuth2 implementation | Aplikasi yang perlu izin pihak ketiga | Authorization: Bearer {access_token} |
Dari pengalaman saya belajar: mulai dari session biasa dulu. Pakai Sanctum kalau ada kebutuhan API sederhana. Baru pertimbangkan Passport kalau aplikasi benar-benar perlu OAuth2 penuh — karena setup-nya lebih kompleks dan memang dirancang untuk kasus penggunaan tertentu.
Alur login yang saya gambar sendiri
Sampai di sini saya coba rangkum alur login dalam satu gambar, supaya kepalaku tidak cuma menyimpan potongan-potongan istilah:

Inti dari gambar itu: Auth::attempt adalah pintu masuknya — ia menerima kredensial, mengeceknya lewat guard, lalu membuat “identitas” di session. Setelah sukses, jangan lupa regenerasi session ID ($request->session()->regenerate()) untuk mencegah session fixation. Detail kecil seperti ini yang dulu tidak pernah saya sadari sebelum belajar Laravel.
use Illuminate\Support\Facades\Auth;
if (Auth::attempt($credentials, $remember)) {
$request->session()->regenerate();
return redirect()->intended('/dashboard');
}
return back()->withErrors([
'email' => 'Kredensial tidak cocok.',
]);Catatan pribadi: pengalaman pertama implementasi login
Saat pertama kali membangun fitur login sendiri (sebelum mengenal Breeze), saya membuat banyak kesalahan konyol. Pertama, saya lupa menambahkan session()->regenerate() setelah login — aplikasi saya rentan terhadap session fixation. Kedua, saya sempat mencoba menyimpan password dengan md5() karena menurut saya “sudah cukup aman” — padahal md5 sudah dianggap tidak aman sejak tahun 2004. Ketiga, saya tidak memakai CSRF protection sehingga form login saya bisa dipakai untuk serangan cross-site request forgery.
Pengalaman ini mengajarkan saya satu hal: jangan menulis sistem autentikasi dari nol. Laravel sudah menyediakan tools yang sudah melalui audit keamanan dan diperbarui secara berkala. Tugas kita sebagai developer adalah memahami cara kerjanya, mengkonfigurasinya dengan benar, dan menambahkan lapisan keamanan yang sesuai kebutuhan. Breeze bukan sekadar “template” — ia adalah referensi implementasi terbaik dari para contributor Laravel.
Yang saya catat hari ini
- Autentikasi = verifikasi identitas + menjaga identitas tetap dikenali (session/token).
config/auth.phpmengatur pasangan guard (cara buktikan) dan provider (sumber data).- Guard ada beberapa tipe: web (session), api (token), sanctum (hybrid) — pilih sesuai kebutuhan.
- Password wajib di-hash (bcrypt lewat facade
Hash); jangan pernah simpan plaintext. - Breeze untuk belajar, Jetstream untuk produksi, Fortify untuk backend-only auth.
- Remember me = parameter boolean kedua di
Auth::attempt(). - Password reset sudah built-in: token → email → form → hash baru.
- 2FA bisa diaktifkan lewat Fortify dengan konfigurasi minimal.
- Social login (Google) memakai Socialite: redirect → callback → firstOrCreate → login.
- Middleware auth, guest, sanctum adalah gerbang yang memfilter akses di tingkat route.
- Jangan pernah menulis autentikasi dari nol — pakai scaffolding yang sudah ada.
Materi ini terasa berat saat pertama dibaca, tapi begitu saya pecah jadi “guard, provider, hash, session”, semuanya jadi puzzle yang nyambung. Episode berikutnya saya ingin lanjut ke gate & policy — soal siapa boleh mengakses apa setelah login. Sampai ketemu di catatan berikutnya!
Komentar Terbaru