Authentication vs Authorization — Auth

Dua konsep yang sering tertukar tapi sangat berbeda: Authentication (AuthN) dan Authorization (AuthZ). Authentication — "Siapa kamu?" Proses memverifikasi…

Setiap request ke halaman yang butuh login dijawab server dengan dua pertanyaan, berurutan. Authentication (disingkat AuthN): "kamu siapa?". Authorization (AuthZ): "kamu boleh ngapain?". Bayangin sekolah: satpam di gerbang mengecek kartu pelajar, itu authentication. Di dalam, ruang guru cuma boleh dimasuki guru, itu authorization. Kartu pelajar Siti asli, tapi tetap gak bikin dia boleh masuk ruang guru.

🧪 Tebakan cepat: Siti sudah login sebagai siswa, lalu mencoba mengisi nilai. Server harus menjawab 401 atau 403? Tebak dulu, jawabannya ada di bagian "401 atau 403".

Contoh yang dipakai sepanjang track: Portal Sekolah

Semua lesson di track Auth memakai satu aplikasi kecil, Portal Sekolah di https://portal.sekolah.test. Penggunanya tiga:

id Nama Email Role
1 Siti [email protected] student (siswa)
2 Pak Andi [email protected] teacher (guru)
3 Bu Dewi [email protected] admin

Route-nya juga tiga. Role adalah peran pengguna, dan permission adalah izin untuk satu jenis aksi:

Route Gunanya Permission yang dibutuhkan Siapa yang punya
GET /students/1/grades lihat rapor Siti grades:read Siti (rapornya sendiri), guru, admin
POST /grades isi nilai grades:write guru, admin
DELETE /users/4 hapus akun Rizky, alumni users:delete admin

Authentication: kamu siapa?

Authentication membuktikan identitas. Caranya: kamu mengirim credential (bukti diri, biasanya email dan password) ke POST /login. Server mencocokkannya. Kalau cocok, server memberi browser sebuah tanda login: session cookie atau token. Browser mengirim tanda itu di setiap request berikutnya, jadi server tahu "ini Siti" tanpa menanyakan password lagi. Cara menyimpan dan membaca tanda itu dibahas di lesson Session, JWT, dan PASETO.

Request tanpa tanda login, atau dengan tanda yang sudah gak berlaku, gagal di pertanyaan pertama.

Authorization: kamu boleh ngapain?

Setelah server tahu siapa kamu, baru dia mengecek izin. Cara paling umum: tiap role punya daftar permission.

const PERMISSIONS = {
  student: ["grades:read"],
  teacher: ["grades:read", "grades:write"],
  admin: ["grades:read", "grades:write", "users:delete"],
};

function authorize(user, permission) {
  if (!user) return false; // belum login: gak punya izin apa pun
  const allowed = PERMISSIONS[user.role] || [];
  return allowed.includes(permission);
}

function handle(user, permission) {
  if (!user) return 401; // 1. authentication gagal
  if (!authorize(user, permission)) return 403; // 2. authorization gagal
  return 200;
}

const siti = { id: 1, name: "Siti", role: "student" };
const andi = { id: 2, name: "Pak Andi", role: "teacher" };
console.log(handle(null, "grades:write")); // 401
console.log(handle(siti, "grades:write")); // 403
console.log(handle(andi, "grades:write")); // 200

Hasil semua kombinasi di Portal Sekolah, persis seperti yang dijawab Lab:

Yang mengirim GET /students/1/grades POST /grades DELETE /users/4
Tamu (belum login) 401 401 401
Siti (student) 200 403 403
Pak Andi (teacher) 200 201 403
Bu Dewi (admin) 200 201 204

Yang lolos dijawab oleh route-nya sendiri: 200 OK untuk rapor, 201 Created karena nilainya tersimpan, 204 No Content karena akunnya terhapus tanpa body jawaban. Di handle tadi, semua yang lolos disederhanakan jadi 200.

401 atau 403

Siti sudah login, jadi pertanyaan pertama lolos. Dia gagal di pertanyaan kedua karena student gak punya grades:write. Jadi jawabannya 403. Itu jawaban tebakannya.

Di Laravel

Laravel memisahkan dua pertanyaan ini dengan rapi. Middleware auth menjawab "kamu siapa?" dan menolak dengan 401. Gate dan Policy menjawab "boleh apa?" dan menolak dengan 403.

// app/Providers/AppServiceProvider.php, di method boot()
Gate::define('delete-user', fn (User $user) => $user->role === 'admin');

// routes/api.php
Route::delete('/users/{user}', [UserController::class, 'destroy'])
    ->middleware(['auth', 'can:delete-user']);

Di dalam middleware buatanmu sendiri, cek izinnya pakai cannot:

if ($request->user()->cannot('delete-user')) {
    abort(403);
}

BelajarWeb.dev sendiri bekerja begitu: route yang butuh login dipasang auth:api, dan guard-nya membaca token PASETO dari header Authorization.

📌 Peta track ini

Lesson berikutnya membangun bagian-bagiannya satu per satu: menyimpan password dengan aman (Password Hashing), mengingat siapa yang login lewat session di server, atau lewat token yang dibawa client (JWT dan PASETO), lalu refresh token, OAuth, dan role yang lebih rinci.

Untuk SPA React dengan API Laravel, tanpa login Google, susunan yang sehat biasanya: access token pendek (misalnya PASETO, umur 15 menit) di memori aplikasi, plus refresh token panjang (misalnya 30 hari) yang opaque, artinya string acak tanpa isi yang bisa dibaca, di cookie HttpOnly yang gak bisa dibaca JavaScript. Kalau access token bocor, umurnya cuma 15 menit. JWT umur 30 hari di localStorage justru kebalikannya: bisa dicuri script mana pun di halaman, dan berlaku lama.

Sisi serangannya ada di track Security: lesson Password Hashing & Storage, Session Management, Cookie Security, dan JWT Security. Track ini fokus ke membangunnya dengan benar.

⚠️ Jebakan yang sering ketemu

TL;DR: Authentication menjawab "kamu siapa?" (login, lalu tanda login di setiap request). Authorization menjawab "kamu boleh ngapain?" (role, permission, pemilik data). Cek siapa dulu, baru izinnya. Gak dikenal: 401 Unauthorized. Dikenal tapi gak berizin: 403 Forbidden. Di Laravel: middleware auth untuk yang pertama, Gate/Policy dengan can dan cannot untuk yang kedua. Semua pengecekan terjadi di server.

Yang akan kamu pelajari