PASETO (Platform-Agnostic Security Tokens) adalah alternatif modern untuk JWT yang didesain untuk menghindari bug desain dan footgun JWT. Dibuat oleh Scott Arciszewski (2018), sekarang semakin populer di backend modern.
Aplikasi BelajarWeb.dev (API yang sedang kamu pakai) memakai PASETO untuk autentikasi API — bukan JWT. Mari kita pahami kenapa dan bagaimana.
Kenapa PASETO, Bukan JWT?
JWT punya track record buruk karena terlalu fleksibel:
| Masalah JWT | Dampak | Penyebab |
|---|---|---|
alg: none accepted |
Bypass signature entirely | Spec mengizinkan "no algorithm" |
| Algorithm confusion (RS256 → HS256) | Verify pakai public key sebagai secret | Server boleh pilih algoritma dari header |
| Downgrade attack | Force weaker algorithm | Multi-algo support |
| Key confusion | HMAC sign key dipakai untuk verify | Ambiguity dalam key type |
PASETO fix ini dengan menghilangkan pilihan: tidak ada alg header yang bisa dimanipulasi, hanya 1 algoritma per versi.
Anatomi PASETO
Format sederhana: 4 bagian dipisah titik.
v4.local.eyJzdWIiOiIxMjMi...VEnKZbB0-4w
v4.public.eyJzdWIiOiIxMjMi...xv8b8VCbC2Mr9Q
│ │ │ │
│ │ │ └─ Signature / tag
│ │ └─ Payload (JSON, base64)
│ └─ "local" atau "public" (lihat di bawah)
└─ Version (v3 atau v4 untuk yang direkomendasikan 2026)
Kontrast dengan JWT:
JWT: eyJ... . eyJ... . eyJ... (3 bagian)
↑ header ↑ payload ↑ signature
Header bisa dimodifikasi — attack surface
PASETO: v4.public. eyJ... . eyJ... (4 bagian dengan version+purpose di depan)
↑ payload ↑ signature
Version+purpose fixed di string, tidak di payload
Local vs Public Mode
PASETO punya 2 use case:
Local = symmetric key (HMAC-like, JWT HS256 equivalent):
- 1 secret key yang shared antara semua pihak yang butuh create/verify token
- Cocok untuk single-app atau backend cluster yang share secret
- Faster, simpler
Public = asymmetric key (JWT RS256 equivalent):
- Private key untuk sign, public key untuk verify
- Cocok untuk multiple consumer (mobile + web + microservice) yang hanya perlu verify
- Private key tidak bocor ke consumer
Generate PASETO di Laravel (Server — yang Dipakai App Ini)
Aplikasi ini pakai paragonie/paseto library.
use ParagonIE\Paseto\Builder;
use ParagonIE\Paseto\Keys\Version4\SymmetricKey;
use ParagonIE\Paseto\Protocol\Version4;
// 1. Generate secret key SEKALI (simpan di env)
$key = SymmetricKey::generate(new Version4);
echo bin2hex($key->raw()); // simpan hasil ini ke PASETO_SECRET
// 2. Buat token saat user login
$token = (new Builder(new Version4))
->setKey($key)
->setPurpose(\"local\")
->setIssuer(\"belajarweb.dev\")
->setSubject((string) $user->id)
->setClaim(\"role\", $user->role)
->setExpiration(new DateTime(\"+24 hours\"))
->setIssuedAt(new DateTime())
->toString();
// Token: v4.local.xxxxx...
return response()->json([\"token\" => $token]);
Verify PASETO
use ParagonIE\Paseto\Parser;
use ParagonIE\Paseto\ProtocolCollection;
use ParagonIE\Paseto\Protocol\Version4;
$parser = Parser::getLocal($key, ProtocolCollection::v4());
try {
$token = $parser->parse($incomingToken);
$userId = $token->get(\"sub\");
$role = $token->get(\"role\");
$exp = $token->get(\"exp\");
// Selalu cek expiry manual juga
if (new DateTime() > new DateTime($exp)) {
abort(401, \"Token expired\");
}
} catch (\ParagonIE\Paseto\Exception\PasetoException $e) {
abort(401, \"Invalid token\");
}
PASETO vs JWT — Decision Matrix
| Aspek | JWT | PASETO |
|---|---|---|
| Standard | RFC 7519 (sudah matang) | Draft, adopsi growing |
| Library support | Setiap bahasa, lusinan opsi | Kurang banyak tapi cukup di major lang |
| Algorithm choice | Banyak (HS256, RS256, ES256, etc.) | 1 per version (v4 = XChaCha20 / Ed25519) |
| Attack surface | Banyak footgun | Sedikit (opinionated) |
| Interop | Hampir semua sistem | Terbatas (belum universal) |
| Size | Relatif kecil | Sedikit lebih besar (prefix version) |
| Kompleksitas implementasi | Mudah salah | Sulit salah |
Rule of thumb:
- Greenfield project tanpa interop eksternal → PASETO (default aman)
- Integrasi dengan sistem existing (OAuth provider, SSO) → JWT (standar industri)
- Third-party API yang verify token → JWT (library mereka pasti support)
Kapan PASETO Lebih Cocok (seperti kasus app ini)
✓ Self-contained auth — kamu kontrol kedua sisi (Laravel backend + React frontend) ✓ Tidak butuh interop dengan OAuth provider eksternal ✓ Developer teamnya masih kecil (menghindari salah konfigurasi JWT) ✓ Butuh keamanan high-assurance (banking, health, financial)
Tips Production
- Rotasi key setiap 90 hari. Simpan
PASETO_CURRENT_KEY+PASETO_PREVIOUS_KEYsupaya token lama tetap valid sampai expire - Version 4 (v4) paling direkomendasikan untuk greenfield — lebih cepat dari v3, pakai XChaCha20-Poly1305
- Jangan taruh data sensitif di payload — sama seperti JWT, payload itu base64, bukan encrypted (kecuali pakai
localmode yang encrypted) - Blacklist untuk logout: sama seperti JWT, PASETO stateless. Kalau butuh server-side revoke, simpan token ID (jti claim) di Redis dengan TTL = token expiry
Resources
- Spec resmi: https://paseto.io
- PHP library yang dipakai app ini: paragonie/paseto
- Laravel package: roberthonorio/laravel-paseto