Pendahuluan — kartu anggota di perpustakaan mini
Artikel ini adalah #61 (ini) di Seri 4: Pemrograman Web Lanjut v2. Di Controller, Service & Eloquent Laravel (#60) kamu sudah punya loket + dapur + tabel. Sekarang langkah 6/8: belajar Auth API dasar — login yang mengeluarkan kartu anggota (token), lalu melindungi pintu yang hanya boleh dibuka pemegang kartu.
Awam: tanpa kartu, siapa saja bisa “masuk ruang staf”. Dengan kartu, tamu harus login dulu. Hari ini kita pasang mesin kartu (Sanctum), buat pintu login, dan uji satu pintu terlindungi.
Domain tetap perpustakaan mini. Belum Capstone penuh (baca + login + tambah) — itu langkah berikutnya.
Prasyarat: sudah selesai Controller, Service & Eloquent Laravel (#60) — proyek
perpustakaan-apijalan,GET /api/bukupernah OK. Fondasi Instal PHP, Composer & Proyek Laravel (#56) / Struktur Folder,.env& Artisan Laravel (#57). Pakai Laravel 13+ — butuh PHP 8.3+.
Spesifikasi fitur — apa yang kita kuasai?
Daftar singkat yang bisa kamu centang di akhir artikel:
- Memasang Laravel Sanctum dari nol (Composer + publish + migrate).
- Membuat pintu POST /api/login yang mengembalikan token (kartu anggota).
- Melindungi pintu contoh GET /api/saya supaya tanpa kartu =
401. - Menguji dengan terminal kedua +
curl.exe/ PowerShell (bukan bilah alamat browser saja).
Awam: urutan nyaman: buka alat -> pasang Sanctum -> siapkan user uji -> buat login -> lindungi pintu -> uji 401 lalu sukses.
Istilah — ringkas untuk kartu anggota
| Istilah | Arti awam | Contoh di artikel ini |
|---|---|---|
| Auth / login | Membuktikan “saya staf yang sah” | POST /api/login |
| Token / kartu anggota | String rahasia yang dibawa di setiap permintaan terlindungi | Header Authorization: Bearer … |
| Sanctum | Paket Laravel untuk kartu anggota API | composer require laravel/sanctum |
401 |
Belum diizinkan — kartu kosong / salah | GET /api/saya tanpa Bearer |
Urutan belajar: kenali kartu -> pasang mesin kartu -> buat login -> lindungi pintu -> uji.
Kenapa auth sekarang?
Validasi di Request & Form Request: Menjaga Input API (#59) menjaga slip kotor. Controller, Service & Eloquent Laravel (#60) merapikan loket. Tanpa auth, pintu “ruang staf” masih terbuka untuk siapa saja yang tahu URL.
Awam: satpam cek slip; petugas kartu cek siapa yang boleh masuk. Hari ini fokus siapa — bukan Capstone penuh.
Artikel ini tetap install-dari-nol untuk mesin kartu: Sanctum dipasang dari nol di bawah — tidak mengandalkan “sudah ada di laptop orang lain”.
Alur — login sampai pintu terlindungi
Persiapan — alat yang kamu buka
Alat yang dipakai di artikel ini (fondasi Instal PHP, Composer & Proyek Laravel (#56) / Struktur Folder, .env & Artisan Laravel (#57) — unduhan baru hanya lewat Composer di bawah):
- Explorer — memastikan folder proyek
perpustakaan-apidan melihat file Controller / Model yang dibuat Artisan. - Terminal — Laragon: menu Terminal · XAMPP: tombol Shell. Jangan asal CMD/PowerShell dari Start Menu (PATH PHP/Composer bisa hilang).
- Terminal kedua — wajib: terminal pertama =
php artisan serve. Terminal kedua = Composer, Artisan lain, dancurl.exe/ PowerShell untuk uji POST/GET ber-token. - Editor teks — Notepad / VS Code — edit Model User, AuthController,
routes/web.php. Tip:notepad app\Http\Controllers\AuthController.phpdari terminal kedua (ganti nama file sesuai yang mau dibuka). - Browser — opsional hari ini. Pintu login & uji token pakai terminal (seperti POST di Request & Form Request: Menjaga Input API (#59)). Browser berguna hanya untuk cek lampu toko masih hidup.
Cara buka terminal kedua (baru pertama kali buka dua terminal sekaligus? ini caranya, jangan tutup yang pertama): Laragon — klik menu Terminal sekali lagi di jendela utama Laragon, sebuah jendela terminal baru akan muncul terpisah dari yang pertama. XAMPP — di XAMPP Control Panel, klik tombol Shell sekali lagi, jendela Shell kedua akan terbuka. Kedua jendela boleh hidup bersamaan — jendela pertama tetap menjalankan php artisan serve, jendela kedua kamu pakai untuk mengetik perintah lain.
Buka terminal Laragon/Shell XAMPP (terminal pertama), masuk folder proyek:
cd C:\laragon\www\perpustakaan-api
Di XAMPP biasanya: cd C:\xampp\htdocs\perpustakaan-api. Sesuaikan path jika foldermu beda.
Nyalakan lampu toko di terminal pertama:
php artisan serve
Biarkan jendela itu hidup. Buka terminal kedua (caranya sudah dijelaskan di atas), cd ke folder proyek yang sama — di sini kamu mengetik Composer, Artisan, dan uji curl.exe.
Awam: Terminal 1 = lampu toko. Terminal 2 = tangan memasang Sanctum + menguji kartu. Editor = menulis login. Browser = boleh dicek sebentar, bukan alat utama uji token.
Pasang Sanctum dari nol
Di terminal kedua (folder perpustakaan-api, lampu toko tetap hidup di terminal pertama):
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
Awam: baris 1 mengunduh mesin kartu. Baris 2 menyalin pengaturan Sanctum ke proyekmu. Baris 3 membuat tabel token di database (SQLite dari fondasi denah Struktur Folder, .env & Artisan Laravel (#57) sudah cukup).
Install-dari-nol: jika composer tidak dikenal, kembali ke Instal PHP, Composer & Proyek Laravel (#56) — pakai Shell XAMPP/Laragon yang sama seperti saat create-project.
Buka model user: notepad app\Models\User.php. Pastikan class memakai trait kartu Sanctum (tempel di dalam class, dekat use HasFactory jika ada):
// Cuplikan app/Models/User.php — di dalam class User
use Laravel\Sanctum\HasApiTokens;
// ... di tubuh class:
use HasApiTokens, HasFactory, Notifiable;
Awam: sesuaikan dengan kerangka file yang sudah ada — jangan hapus namespace / nama class. Yang penting: HasApiTokens ikut dipakai supaya user bisa mengeluarkan token.
Siapkan satu user uji
Masih di terminal kedua. Buat / perbarui satu staf uji dengan perintah satu tembakan (tidak perlu masuk mode percakapan):
php artisan tinker --execute="\App\Models\User::updateOrCreate(['email'=>'staf@perpustakaan.test'], ['name'=>'Staf Mini','password'=>bcrypt('password')]);"
Awam: ini bukan chat panjang. tinker --execute="…" = minta Artisan menjalankan satu baris PHP lalu selesai. Email uji: staf@perpustakaan.test · sandi: password (hanya untuk belajar di laptopmu).
Controller login — loket kartu
Di terminal kedua:
php artisan make:controller AuthController
Buka file: notepad app\Http\Controllers\AuthController.php. Jangan hapus namespace dan kerangka class. Tambahkan use di atas class, lalu method login di dalam class:
// Cuplikan AuthController — loket login
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
public function login(Request $request): JsonResponse
{
$data = $request->validate([
'email' => ['required', 'email'],
'password' => ['required', 'string'],
]);
$user = User::query()->where('email', $data['email'])->first();
if (! $user || ! Hash::check($data['password'], $user->password)) {
return response()->json(['message' => 'Belum diizinkan — email/sandi salah'], 401);
}
$token = $user->createToken('kartu-staf')->plainTextToken;
return response()->json([
'message' => 'Login berhasil — simpan kartu (token)',
'token' => $token,
'token_type' => 'Bearer',
]);
}
Awam: kalau email/sandi salah = 401 + pesan jelas. Kalau benar = JSON berisi token. Simpan token itu; nanti ditempel di header.
Pintu saya — contoh terlindungi
Tambahkan method di Controller yang sama (atau Controller kecil lain). Cuplikan untuk AuthController:
// Cuplikan AuthController — siapa yang sedang masuk
public function saya(Request $request): JsonResponse
{
$user = $request->user();
return response()->json([
'message' => 'Kartu diterima',
'data' => [
'id' => $user->id,
'name' => $user->name,
'email' => $user->email,
],
]);
}
Buka notepad routes\web.php. Tambahkan (di bawah route yang sudah ada):
// Cuplikan routes/web.php — login + pintu ber-kartu
use App\Http\Controllers\AuthController;
Route::post('/api/login', [AuthController::class, 'login']);
Route::middleware('auth:sanctum')->get('/api/saya', [AuthController::class, 'saya']);
Simpan. Pastikan serve masih hidup di terminal pertama.
Awam: auth:sanctum = satpam kartu di pintu /api/saya. Tanpa header Bearer yang sah, tamu ditolak.
Cek izin api/* — supaya login tidak ditolak 419
Laravel punya satpam lobi bawaan bernama CSRF yang melindungi formulir web: ia menolak semua kiriman POST yang tidak datang dari halaman browser milik situs itu sendiri. Karena kita menguji POST /api/login dari terminal (bukan browser), tanpa izin khusus jawabannya adalah {"message":"CSRF token mismatch."} dengan kode 419 — bukan token.
Kalau di dalam withMiddleware sudah ada 'api/*' (biasanya dari Request & Form Request: Menjaga Input API (#59)) — lewati langkah ini. Penjelasan panjangnya ada di artikel itu.
Belum ada? Pastikan terminal kedua sudah di folder proyek (cd ke perpustakaan-api), lalu notepad bootstrap\app.php. Jangan menempel blok ->withMiddleware(...) baru di dalam fungsi yang sudah ada. Kerja di dalam fungsi itu: hapus // kalau masih ada, biarkan baris lain, lalu tempel hanya:
// Tempel di dalam withMiddleware yang sudah ada — jangan buat withMiddleware baru
$middleware->preventRequestForgery(except: [
'api/*',
]);
Hasil yang benar kira-kira begini (boleh ada baris lain di sekitarnya):
->withMiddleware(function (Middleware $middleware): void {
$middleware->preventRequestForgery(except: [
'api/*',
]);
})
Awam: except = “kecuali”. Di Laravel 13 nama resminya preventRequestForgery; nama lama validateCsrfTokens masih sama artinya.
Setiap kali menyimpan bootstrap\app.php, matikan serve di terminal pertama (Ctrl+C) lalu php artisan serve lagi — file itu hanya dibaca saat aplikasi mulai.
Tenang, kartunya tetap aman. Pagar yang menjaga /api/saya adalah petugas kartu Sanctum yang kamu pasang di artikel ini — CSRF itu satpam lobi untuk formulir browser, jenis yang berbeda.
Uji di terminal kedua
Jangan andalkan bilah alamat browser untuk POST login. Ikuti pola uji di Request & Form Request: Menjaga Input API (#59).
Opsi A — curl.exe (Windows 10/11 biasanya sudah punya; ketik curl.exe agar tidak tertukar di PowerShell):
1) Login — ambil token
curl.exe -s -X POST http://127.0.0.1:8000/api/login ^
-H "Content-Type: application/json" ^
-H "Accept: application/json" ^
-d "{\"email\":\"staf@perpustakaan.test\",\"password\":\"password\"}"
Awam — salin token: di jawaban JSON cari kunci "token". Salin hanya string di antara tanda kutip (panjang, tanpa spasi di ujung). Jangan salin kata Bearer dari JSON — kata Bearer ditulis nanti di header. Ganti GANTI_DENGAN_TOKEN di perintah berikutnya dengan string itu.
Awam — cara salin teks dari terminal Windows: blok teks dengan klik kiri lalu tahan sambil digeser (klik-drag), lepas tombol mouse untuk menyalin otomatis. Tempel dengan klik kanan di jendela terminal (bukan Ctrl+V, terminal bawaan Windows kadang tidak mendukungnya).
2) Tanpa kartu — harus 401
curl.exe -s http://127.0.0.1:8000/api/saya ^
-H "Accept: application/json"
Kamu harus melihat pesan seperti “Belum diizinkan” / unauthenticated — bukan profil staf.
3) Dengan kartu — harus 200 + data nama/email
curl.exe -s http://127.0.0.1:8000/api/saya ^
-H "Accept: application/json" ^
-H "Authorization: Bearer GANTI_DENGAN_TOKEN"
Opsi B — PowerShell (kalau kutip curl ribet):
# Login — catat .token dari hasil
$login = Invoke-RestMethod -Method Post -Uri http://127.0.0.1:8000/api/login `
-ContentType 'application/json' -Headers @{ Accept = 'application/json' } `
-Body '{"email":"staf@perpustakaan.test","password":"password"}'
$login.token
# Dengan kartu — ganti isi string token
Invoke-RestMethod -Method Get -Uri http://127.0.0.1:8000/api/saya `
-Headers @{ Accept = 'application/json'; Authorization = 'Bearer GANTI_DENGAN_TOKEN' }
Opsi C — alat uji API berjendela (Postman / Insomnia — opsional). Login: metode POST, URL http://127.0.0.1:8000/api/login, body JSON email+password, header Accept + Content-Type = application/json. Lalu GET /api/saya dengan header Authorization: Bearer … (tempel token). Ide sama: tanpa kartu ditolak, dengan kartu diterima.
Awam: baris Accept: application/json meminta jawaban JSON (bukan halaman HTML error panjang). ^ di CMD = lanjut baris; di PowerShell pakai backtick ` atau satu baris. Selalu curl.exe, bukan alias curl.
Pola Dasar — empat langkah kartu bersih
-
1
Buka alat
Terminal 1serve· Terminal 2 Composer/Artisan/curl · Editor. -
2
Pasang Sanctum
composer require· publish · migrate ·HasApiTokens. -
3
Login + pintu
POST /api/login·GET /api/saya+auth:sanctum. -
4
Uji 401 lalu 200
Tanpa Bearer ditolak; dengan Bearer menampilkan profil singkat.
Demo kartu anggota — file mandiri
Latihan ide tanpa mengubah proyek Laravel:
- Buka editor, buat file baru, tempel cuplikan di bawah, simpan sebagai
laravel_auth_api_dasar_demo.php(boleh di Desktop). - Buka terminal di folder file itu (Explorer: Shift+klik kanan -> “Open in Terminal” / “Buka di Terminal”, atau
cdmanual). Pastikanphp -vjalan. - Jalankan:
php laravel_auth_api_dasar_demo.php— layar mensimulasikan login gagal/sukses dan cek kartu.
File ini mensimulasikan peran — tidak mengubah proyek Laravel-mu:
<?php
declare(strict_types=1);
function demo(): void
{
$staf = ['email' => 'staf@perpustakaan.test', 'password' => 'password'];
echo "=== Simulasi Auth API dasar ===", PHP_EOL;
$salah = loginSimulasi('salah@x.test', 'x', $staf);
echo "Login salah -> ", $salah['message'], " (HTTP ", $salah['status'], ")", PHP_EOL;
$ok = loginSimulasi('staf@perpustakaan.test', 'password', $staf);
echo "Login OK -> token: ", $ok['token'], PHP_EOL;
$tanpa = cekKartuSimulasi(null);
echo "Tanpa kartu -> ", $tanpa['message'], " (HTTP ", $tanpa['status'], ")", PHP_EOL;
$dengan = cekKartuSimulasi($ok['token'] ?? null);
echo "Dengan kartu -> ", $dengan['message'], " · ", ($dengan['data']['email'] ?? '-'), PHP_EOL;
echo PHP_EOL, "Langkah sungguhan: Sanctum -> user uji -> AuthController -> route -> curl.exe.", PHP_EOL;
}
/**
* Simulasi login — kembalikan status + pesan (+ token jika sukses).
*/
function loginSimulasi(string $email, string $password, array $staf): array
{
if ($email !== $staf['email'] || $password !== $staf['password']) {
return ['status' => 401, 'message' => 'Belum diizinkan — email/sandi salah'];
}
return [
'status' => 200,
'message' => 'Login berhasil',
'token' => 'kartu-demo-'.substr(sha1($email), 0, 8),
];
}
/**
* Simulasi cek kartu di pintu terlindungi.
*/
function cekKartuSimulasi(?string $token): array
{
if ($token === null || $token === '') {
return ['status' => 401, 'message' => 'Belum diizinkan'];
}
return [
'status' => 200,
'message' => 'Kartu diterima',
'data' => ['email' => 'staf@perpustakaan.test'],
];
}
demo();
Awam: demo() hanya latihan di terminal. Setelah paham, kerjakan langkah Sanctum di folder perpustakaan-api. declare(strict_types=1); membuat tipe lebih ketat — boleh diikuti, tidak wajib dihafal.
Kesalahan umum
| Gejala | Penyebab tipikal | Perbaikan awam |
|---|---|---|
CSRF token mismatch / kode 419 saat login |
Izin api/* di bootstrap\app.php belum dipasang, atau serve belum dinyalakan ulang |
Pasang preventRequestForgery(except: ['api/*']) (jangan timpa baris lain), lalu Ctrl+C dan php artisan serve lagi |
composer tidak dikenal |
Terminal Start Menu / PATH | Pakai Laragon Terminal atau Shell XAMPP — lihat Persiapan |
| Class HasApiTokens not found | Sanctum belum require / trait belum di-use | Ulangi composer require laravel/sanctum + cek User.php |
| 401 terus saat login | User uji belum dibuat / sandi beda | Jalankan ulang perintah tinker --execute di atas |
401 di /api/saya meski sudah login |
Header Bearer kosong / token salah tempel | Salin token utuh dari kunci "token"; format Authorization: Bearer … (satu spasi setelah Bearer) |
| Jawaban HTML panjang / bukan JSON | Lupa header Accept: application/json |
Tambahkan header Accept seperti di Opsi A |
curl aneh di PowerShell |
Alias curl tertukar |
Pakai curl.exe, Opsi B PowerShell, atau Opsi C |
| Connection refused | serve mati |
Nyalakan lagi di terminal pertama setelah cd ke proyek |
Latihan
- Jalankan demo PHP di atas — pastikan kasus login salah = 401 simulasi.
- Di proyek: pasang Sanctum, buat user uji, login, lalu bandingkan respons tanpa vs dengan Bearer.
- Jelaskan ke teman: beda singkat “satpam slip (validasi)” dan “satpam kartu (auth)” dengan bahasa toko.
FAQ
Terminal mana yang harus dibuka?
Laragon: menu Terminal · XAMPP: tombol Shell. Satu jendela untuk serve, jendela kedua untuk Composer/Artisan/curl.exe.
Harus Postman?
Tidak. curl.exe / PowerShell cukup. Alat berjendela (Opsi C) hanya jika kutip di terminal terasa ribet.
Token yang mana yang disalin?
Dari jawaban login, kunci "token" — string panjang di antara kutip. Jangan salin seluruh JSON. Jangan tulis ulang kata Bearer dua kali.
Apa itu Bearer tanpa istilah sulit?
Bearer = “bawa kartu di header”. Isinya token dari login. Tanpa itu, pintu /api/saya menolak.
Kenapa pakai Sanctum, bukan session web biasa?
API JSON sering dipanggil dari terminal/aplikasi lain. Token mudah dibawa di header. Session cookie lebih cocok halaman web ber-form.
Apa hubungan dengan artikel loket?
Controller, Service & Eloquent Laravel (#60) merapikan daftar buku. #61 (ini) menambah siapa yang boleh masuk pintu staf.
Ke mana setelah ini?
Berikutnya: Capstone: API Perpustakaan (Baca + Login + Tambah) (#62) — menggabungkan baca katalog, login, dan tambah buku dengan kartu.
Kesimpulan
Kamu sudah memasang Auth API dasar: Sanctum dari nol, login mengeluarkan token, pintu /api/saya terlindungi, diuji lewat terminal saat artisan serve hidup. Ini langkah 6/8 jalur Laravel di Seri 4.
Seri 4 progress: langkah #61 (ini) · 6/8 jalur Laravel · prasyarat: Controller, Service & Eloquent Laravel (#60) LIVE. Berikutnya: Capstone: API Perpustakaan (Baca + Login + Tambah) (#62).