← Semua pembelajaran / Laravel Nol → Enterprise
Fase 4 · Autentikasi & Keamanan

Sanctum — token API

Sanctum menawarkan dua mode yang sering tertukar: token personal untuk klien pihak ketiga, dan autentikasi berbasis cookie untuk SPA di domain yang sama. Memilih yang salah menghasilkan sesi yang selalu gagal.

Sumber asli laravel.com Resmi Rangkuman ~6 menit baca

Intisari

  • Mode token: klien mengirim Authorization: Bearer …. Untuk mobile dan integrasi.
  • Mode SPA: memakai cookie sesi Laravel biasa. Untuk frontend di domain yang sama.
  • Token disimpan sebagai hash; nilai aslinya hanya muncul sekali saat dibuat.
  • Ability membatasi apa yang boleh dilakukan sebuah token — dan tidak pernah bisa melebihi izin pemiliknya.
  • Pakai Passport hanya kalau kamu memang harus jadi server OAuth2 bagi aplikasi pihak ketiga.

Memasang

php artisan install:api      # memasang Sanctum + membuat routes/api.php
class User extends Authenticatable
{
    use HasApiTokens;        // ← ditambahkan oleh install:api
}

Mode 1 — token personal

// Menerbitkan token
$token = $user->createToken(
    name: 'aplikasi-mobile',
    abilities: ['artikel:baca', 'artikel:tulis'],
    expiresAt: now()->addDays(30),
);

return ['token' => $token->plainTextToken];   // HANYA muncul sekarang
curl https://contoh.test/api/artikel \
  -H "Authorization: Bearer 1|AbCdEf..." \
  -H "Accept: application/json"
// routes/api.php
Route::middleware('auth:sanctum')->group(function () {
    Route::get('/artikel', [ArtikelController::class, 'index']);

    Route::post('/artikel', [ArtikelController::class, 'store'])
        ->middleware('ability:artikel:tulis');
});

Nilai token hanya ada satu kali. Database menyimpan hash-nya, persis seperti password. Kalau pengguna kehilangan token, tidak ada cara memulihkannya — yang bisa dilakukan hanya mencabut dan menerbitkan yang baru. Ini fitur: bocornya isi tabel personal_access_tokens tidak memberi penyerang satu pun token yang bisa dipakai.

Mode 2 — SPA di domain yang sama

SANCTUM_STATEFUL_DOMAINS=portal.test,localhost:5173
SESSION_DOMAIN=.portal.test
# 1. Ambil cookie CSRF lebih dulu
GET /sanctum/csrf-cookie

# 2. Login seperti form biasa — hasilnya cookie sesi
POST /login

# 3. Panggilan berikutnya cukup mengirim cookie; tidak ada token sama sekali
Mode tokenMode SPA
UntukMobile, integrasi pihak ketiga, skripFrontend di domain yang sama
Dikirim lewatHeader AuthorizationCookie
CSRFTidak relevanWajib — ambil /sanctum/csrf-cookie
KedaluwarsaDitentukan saat dibuatMengikuti masa sesi
Dicabut denganHapus baris tokenLogout

Kesalahan konfigurasi paling umum di mode SPA. Frontend berjalan di localhost:5173 tapi domain itu tidak terdaftar di SANCTUM_STATEFUL_DOMAINS — sehingga Sanctum memperlakukannya sebagai klien token, tidak menemukan header Authorization, dan menjawab 401 pada setiap permintaan. Gejalanya: "login berhasil tapi permintaan berikutnya selalu 401".

Mengelola token

$user->tokens;                                  // daftar
$user->tokens()->where('name', 'lama')->delete();
$user->currentAccessToken()->delete();          // logout perangkat ini saja
$user->tokens()->delete();                      // cabut semuanya

// Di dalam kode aplikasi
if ($request->user()->tokenCan('artikel:tulis')) { /* ... */ }

Ability membatasi, tidak memberi. Token dengan ability artikel:hapus milik pengguna yang policy-nya tidak mengizinkan penghapusan tetap tidak bisa menghapus. Urutannya: policy dulu, ability kemudian. Ability berguna untuk memberi klien pihak ketiga bagian dari izin pemiliknya, bukan untuk memperluasnya.

Praktik yang layak diikuti

  1. Beri masa berlaku pada setiap token; token abadi adalah kredensial abadi.
  2. Satu token per perangkat atau per integrasi, dengan nama yang bermakna — supaya bisa dicabut satu per satu.
  3. Ability yang sesempit mungkin; jangan menerbitkan token serba bisa untuk satu kebutuhan sempit.
  4. Batasi laju rute penerbitan token — ia adalah endpoint yang menarik untuk ditebak-tebak.
  5. Cabut seluruh token saat pengguna mengganti password.

Latihan: buat endpoint POST /api/token yang memverifikasi email dan password lalu menerbitkan token dengan ability artikel:baca saja. Panggil GET /api/artikel dengan token itu (harus berhasil), lalu POST /api/artikel (harus 403). Terakhir, cabut tokennya dan pastikan permintaan berikutnya menjadi 401.

Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.