Kalau kamu baru mulai belajar authentication di Laravel, kamu pasti pernah bingung melihat daftar namanya: Breeze, Jetstream, Fortify, Sanctum, Passport. Semuanya berkaitan dengan auth, tapi tidak jelas mana yang harus dipakai dan apa bedanya.
Sebelum masuk ke kode, kita perlu ngerti dulu siapa yang melakukan apa β karena di sinilah kebingungan itu biasanya berasal.
πΊοΈ Peta Ekosistem Auth Laravel
Bayangkan auth di Laravel seperti restoran. Ada tiga lapisan yang berbeda tugasnya:
Breeze / Jetstream
β
"Ruang makan + dekorasi" β UI yang dilihat user (form login, register, halaman profil)
Fortify
β
"Dapur" β engine auth yang memproses semua logika (validasi, login, reset password)
Sanctum / Passport
β
"Sistem kasir khusus" β manajemen token untuk API dan SPA
Breeze adalah starter kit yang paling simpel β dia install Fortify di balik layar dan sekaligus menyediakan halaman-halaman Blade (atau Inertia/Vue) yang sudah jadi.
Fortify adalah headless authentication β dia hanya menyediakan logika dan route, tanpa UI sama sekali. Cocok kalau kamu mau bikin tampilan sendiri atau butuh auth untuk SPA.
Sanctum dipakai untuk menerbitkan token API β baik personal access token untuk mobile app maupun cookie-based auth untuk SPA.
π Bagian 1 β Alur Authentication Breeze (Web / Session)
Install
composer require laravel/breeze --dev
php artisan breeze:install blade # versi Blade biasa
# atau
php artisan breeze:install vue # versi Inertia + Vue
npm install && npm run dev
php artisan migrate
Setelah ini, Laravel menyediakan route, controller, dan view untuk: register, login, logout, forgot password, reset password, dan verifikasi email.
Alur Register
Ini yang terjadi ketika pengguna baru mengisi form registrasi:
1. User isi form β POST /register
2. RegisteredUserController@store dipanggil
3. Validasi input (nama, email, password)
βββ Email harus unik, password minimal 8 karakter
4. User::create([...]) β password otomatis di-hash lewat bcrypt
5. Auth::login($user) β user langsung di-login setelah register
6. Session dibuat, session ID disimpan di cookie browser
7. Redirect ke /dashboard
Di balik layar, proses ini ditangani Fortify β Breeze hanya menyediakan tampilan form-nya.
Alur Login
1. User isi email + password β POST /login
2. Fortify::authenticateUsing dipanggil
βββ Default: cek email + password dengan Auth::attempt()
3. Auth::attempt(['email' => ..., 'password' => ...])
βββ Ambil user dari database berdasarkan email
βββ Verifikasi password dengan Hash::check()
4. Kalau cocok β Auth::login($user)
βββ Session dibuat
βββ Session ID dikirim ke browser via cookie
5. Redirect ke /dashboard (atau intended URL)
Kalau gagal β redirect balik ke form login dengan error
Session β Apa yang Sebenarnya Terjadi
Ini bagian yang sering tidak dipahami secara utuh.
Browser Server (Laravel)
β β
β POST /login (email + password) β
β ββββββββββββββββββββββββββββββββββΊ β
β β Validasi credentials
β β Buat session
β β Simpan user_id di session storage
β β
β Set-Cookie: laravel_session=xyz β
β ββββββββββββββββββββββββββββββββββ β
β β
β GET /dashboard β
β Cookie: laravel_session=xyz β
β ββββββββββββββββββββββββββββββββββΊ β
β β Baca cookie β cari session
β β Session ada β ambil user_id
β β Auth::user() tersedia
β β
β Response: halaman dashboard β
β ββββββββββββββββββββββββββββββββββ β
Yang disimpan di cookie browser bukan data user β hanya ID session. Data aslinya (termasuk user_id) tersimpan di server (file, database, atau Redis tergantung konfigurasi SESSION_DRIVER).
Middleware auth β Penjaga Route
Setelah user login, route yang butuh autentikasi dilindungi dengan middleware auth:
// routes/web.php
Route::middleware('auth')->group(function () {
Route::get('/dashboard', DashboardController::class);
Route::resource('/posts', PostController::class);
});
Yang terjadi ketika request masuk ke route ini:
Request β Middleware auth dipanggil
β
βββ Auth::check() β apakah session punya user yang valid?
β
βββ Ya β lanjutkan ke controller
β
βββ Tidak β redirect ke /login
Mengakses user yang sedang login di controller:
// Cara 1 β lewat facade
$user = Auth::user();
$id = Auth::id();
// Cara 2 β lewat request (lebih disukai di controller)
$user = $request->user();
// Cara 3 β helper global
$user = auth()->user();
Alur Logout
// AuthenticatedSessionController@destroy
public function destroy(Request $request): RedirectResponse
{
Auth::guard('web')->logout();
// Hapus data session saat ini
$request->session()->invalidate();
// Regenerate CSRF token untuk keamanan
$request->session()->regenerateToken();
return redirect('/');
}
Kustomisasi Logika Login
Fortify memungkinkan kamu mengganti logika autentikasi sepenuhnya lewat Fortify::authenticateUsing():
// app/Providers/FortifyServiceProvider.php
use Laravel\Fortify\Fortify;
use Illuminate\Support\Facades\Hash;
public function boot(): void
{
// Ganti logika default dengan logika kustom
Fortify::authenticateUsing(function (Request $request) {
$user = User::where('email', $request->email)->first();
if ($user && Hash::check($request->password, $user->password)) {
// Tambahkan kondisi ekstra β misalnya cek status akun
if (! $user->is_active) {
return null; // tolak login
}
return $user;
}
return null; // credentials salah
});
}
π‘ Bagian 2 β Authentication untuk API (Token-based)
Untuk API yang dikonsumsi mobile app atau SPA, session tidak relevan β karena HTTP stateless dan client tidak bisa menyimpan cookie dengan cara yang sama.
Solusinya adalah token: server menerbitkan token saat login, client menyimpannya, dan menyertakannya di setiap request berikutnya di header Authorization.
Install Sanctum
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
Tambahkan trait HasApiTokens ke model User:
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
}
Alur Login API
// routes/api.php
Route::post('/login', [AuthController::class, 'login']);
Route::middleware('auth:sanctum')->group(function () {
Route::get('/me', [AuthController::class, 'me']);
Route::post('/logout', [AuthController::class, 'logout']);
});
// app/Http/Controllers/AuthController.php
class AuthController extends Controller
{
public function login(Request $request)
{
$request->validate([
'email' => 'required|email',
'password' => 'required',
]);
// Cek credentials
if (! Auth::attempt($request->only('email', 'password'))) {
return response()->json([
'message' => 'Email atau password salah'
], 401);
}
$user = Auth::user();
// Buat token β beri nama sesuai device/keperluan
$token = $user->createToken('mobile-app')->plainTextToken;
return response()->json([
'token' => $token,
'user' => $user,
]);
}
public function me(Request $request)
{
// Auth::user() tersedia karena middleware auth:sanctum
return response()->json($request->user());
}
public function logout(Request $request)
{
// Hapus hanya token yang sedang dipakai
$request->user()->currentAccessToken()->delete();
return response()->json(['message' => 'Logged out']);
}
}
Alur Request API dengan Token
Mobile App Laravel API
β β
β POST /api/login β
β {email, password} β
β βββββββββββββββββββββββββββββββΊ β
β β Validasi β buat token
β {token: "1|abc123..."} β
β βββββββββββββββββββββββββββββββ β
β β
β Simpan token di storage lokal β
β β
β GET /api/me β
β Authorization: Bearer 1|abc123 β
β βββββββββββββββββββββββββββββββΊ β
β β Middleware auth:sanctum
β β Cari token di tabel personal_access_tokens
β β Token valid β ambil user
β β
β {id: 1, name: "Budi", ...} β
β βββββββββββββββββββββββββββββββ β
π Bagian 3 β Session Auth vs Token Auth
Ini perbandingan yang perlu dipahami sebelum memilih pendekatan:
Session Auth (Breeze / web) Token Auth (Sanctum / API)
ββββββββββββββββββββββββββββ ββββββββββββββββββββββββββ
State tersimpan di server Stateless β server tidak
(file / database / redis) simpan state apapun
Identifikasi via cookie Identifikasi via header
laravel_session=xyz Authorization: Bearer xyz
CSRF protection dibutuhkan CSRF tidak relevan
(karena cookie otomatis terkirim) (token harus eksplisit dikirim)
Cocok untuk: Cocok untuk:
- Web app tradisional - REST API
- Server-side rendered (Blade) - Mobile app
- SPA same-domain - SPA cross-domain
πΊοΈ Gambaran Besar β Semua Komponen dan Posisinya
Permintaan login dari user
β
βΌ
βββββββββββββββββββββββββββββββββββ
β routes/web.php β
β POST /login β
β Middleware: guest β β hanya boleh diakses kalau belum login
ββββββββββββββββ¬βββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββ
β Fortify (engine di balik layar)β
β authenticateUsing() β
β β Auth::attempt() β
β β Hash::check() β
ββββββββββββββββ¬βββββββββββββββββββ
β
βββββββββ΄ββββββββ
β Berhasil β Gagal
βΌ βΌ
Auth::login() redirect + error
Session dibuat
β
βΌ
βββββββββββββββββββββββββββββββββββ
β Route berikutnya β
β Middleware: auth β β cek session / token
β Auth::user() tersedia β
β Controller berjalan β
βββββββββββββββββββββββββββββββββββ
π Perbandingan Breeze vs Fortify vs Sanctum
| Breeze | Fortify | Sanctum | |
|---|---|---|---|
| Menyediakan UI | β Blade / Inertia | β | β |
| Logika auth | Lewat Fortify | β Langsung | β |
| Untuk web (session) | β | β | β (SPA) |
| Untuk API (token) | β | β | β |
| Install otomatis | β | Manual | Manual |
| Cocok untuk | Starter cepat | Kustomisasi penuh | API / Mobile / SPA |
π‘ Ingat!
Dua hal yang paling sering bikin bingung di auth Laravel:
Pertama β Breeze bukan pengganti Fortify. Breeze menggunakan Fortify. Kalau kamu install Breeze, Fortify sudah ada di dalamnya. Kalau kamu mau kustomisasi logika login, kamu edit di Fortify β bukan di Breeze.
Kedua β middleware auth dan auth:sanctum itu berbeda. auth (tanpa guard) menggunakan session β cocok untuk route web. auth:sanctum membaca token dari header Authorization β cocok untuk route API. Salah pilih guard, request yang valid pun bisa ditolak.
Dan satu kebiasaan yang sangat direkomendasikan: selalu pisahkan route web di routes/web.php dan route API di routes/api.php. Keduanya punya middleware group yang berbeda β web group punya session dan CSRF, api group tidak.