JWT vs Session Authentication: Memahami Perbedaan dan Kapan Menggunakannya

## Introduction Dalam membangun aplikasi web modern, keamanan otentikasi adalah salah satu aspek yang tidak boleh diabaikan. Dua pendekatan populer un...

JWT vs Session Authentication: Memahami Perbedaan dan Kapan Menggunakannya

Introduction

Dalam membangun aplikasi web modern, keamanan otentikasi adalah salah satu aspek yang tidak boleh diabaikan. Dua pendekatan populer untuk mengelola sesi pengguna adalah JWT (JSON Web Token) dan Session-based authentication (biasa menggunakan cookie dan server-side storage). Meskipun keduanya bertujuan untuk mengidentifikasi pengguna yang telah login, cara kerjanya, kelebihan, dan kekurangannya sangat berbeda. Artikel ini akan menjelaskan konsep dasar masing-masing, memberikan contoh sederhana dalam Node.js/Express, dan membantu Anda memutuskan kapan sebaiknya menggunakan JWT atau Session.

Pembahasan

Apa itu Session Authentication?

  • Konsep: Setelah login berhasil, server membuat sebuah session identifier (misal:
    code
    sessionId
    ) dan menyimpan data sessi (user ID, role, dll.) di penyimpanan server seperti memori, Redis, atau database. Identifier ini lalu dikirim ke klien sebagai cookie (
    code
    Set-Cookie: sessionId=abc123; HttpOnly; Secure
    ).
  • Keamanan: Cookie biasanya ditandai
    code
    HttpOnly
    dan
    code
    Secure
    sehingga tidak dapat diakses oleh JavaScript dan hanya dikirim melalui HTTPS.
  • Kelebihan:
    • Mudah untuk melakukan logout karena cukup menghapus data sessi di server.
    • Ukuran cookie kecil (hanya ID), sehingga tidak menambah beban jaringan signifikan.
  • Kekurangan:
    • Memerlukan penyimpanan server yang harus di-skala (misalnya menggunakan Redis cluster) ketika aplikasi menggunakan banyak instance.
    • Tidak cocok untuk arsitektur mikro‑layanan yang sepenuhnya stateless.

Apa itu JWT?

  • Konsep: JWT adalah token yang dikodekan dalam format JSON dan ditandatangani secara kriptografis (HMAC atau RSA). Token berisi claims seperti
    code
    sub
    (subject/user ID),
    code
    exp
    (expiration), dan data kustom lain. Token ini dikirim ke klien (biasa dalam header
    code
    Authorization: Bearer <token>
    atau cookie) dan divalidasi oleh server hanya melalui verifikasi tanda tangan, tanpa perlu menyimpan state di server.
  • Keamanan: Asalkan kunci rahasia (secret) atau kunci privat tidak bocor, token tidak dapat diubah tanpadeteksi.
  • Kelebihan:
    • Stateless: server tidak perlu menyimpan session, sehingga mudah di‑scale dan cocok untuk mikro‑layanan.
    • Token dapat berisi informasi yang dibutuhkan oleh layanan lain (misal: role, permissions) tanpa perlu panggilan tambahan ke server otentikasi.
  • Kekurangan:
    • Ukuran token lebih besar (biasa beberapa ratus byte) karena mengandung payload yang ditandatangani.
    • Pembatalan token sebelum masa berlaku (
      code
      exp
      ) membutuhkan mekanisme tambahan seperti token blacklist atau revocation list.
    • Tidak disarankan untuk menyimpan data sensitif dalam payload karena token hanya base64url di‑encode (bisa dengan mudah didekode).

Kapan Memilih Mana?

SituasiDirekomendasikan
Aplikasi monolitik dengan sedikit instance, ingin logout instan, dan tidak mau mengelola ukuran tokenSession
Sistem mikro‑layanan, API gateway, atau layanan yang perlu skala horizontal tanpa menyimpan stateJWT
Butuh token yang dapat dipakai oleh banyak layanan pihak ketiga (misal: login dengan OAuth2)JWT
Kebutuhan akan pencabutan akses segera (misal: perubahan password) tanpa menunggu token kadaluarsaSession ( atau JWT + blacklist )

Contoh (jika ada)

Berikut contoh sederhana mengimplementasikan keduanya dengan Node.js + Express. Kita asumsikan sudah ada fungsi

code
verifyPassword(email, password)
yang mengembalikan
code
user
jika berhasil.

javascript
// ---- Dependency ----
const express = require('express');
const jwt = require('jsonwebtoken');
const session = require('express-session');
const RedisStore = require('connect-redis')(session);
const redis = require('redis');
const app = express();

app.use(express.json());

// ---------- SESSION BASED ----------
const redisClient = redis.createClient({ url: 'redis://localhost:6379' });
redisClient.connect().catch(console.error);

app.use(
  session({
    store: new RedisStore({ client: redisClient }),
    secret: 's3cr3t-s3ss10n',
    resave: false,
    saveUninitialized: false,
    cookie: { httpOnly: true, secure: false, maxAge: 24 * 60 * 60 * 1000 }, // 1 hari
  })
);

app.post('/login/session', async (req, res) => {
  const { email, password } = req.body;
  const user = await verifyPassword(email, password);
  if (!user) return res.status(401).json({ msg: 'Invalid credentials' });

  // Simpan user ID ke dalam session
  req.session.userId = user.id;
  return res.json({ msg: 'Login successful' });
});

app.get('/profile/session', (req, res) => {
  if (!req.session.userId)
    return res.status(401).json({ msg: 'Not authenticated' });
  // Ambil data user dari DB atau cache
  res.json({ userId: req.session.userId, msg: 'Session based profile' });
});

// ---------- JWT BASED ----------
const JWT_SECRET = 'jwt-s3cr3t-key';
const JWT_EXPIRES_IN = '1h';

app.post('/login/jwt', async (req, res) => {
  const { email, password } = req.body;
  const user = await verifyPassword(email, password);
  if (!user) return res.status(401).json({ msg: 'Invalid credentials' });

  const token = jwt.sign(
    { sub: user.id, role: user.role }, // payload
    JWT_SECRET,
    { expiresIn: JWT_EXPIRES_IN }
  );
  return res.json({ token });
});

function authenticateJWT(req, res, next) {
  const auth = req.headers.authorization;
  if (!auth || !auth.startsWith('Bearer '))
    return res.status(401).json({ msg: 'Missing or malformed token' });
  const token = auth.slice(7);
  jwt.verify(token, JWT_SECRET, (err, payload) => {
    if (err) return res.status(401).json({ msg: 'Invalid or expired token' });
    req.user = payload; // { sub, role, iat, exp }
    next();
  });
}

app.get('/profile/jwt', authenticateJWT, (req, res) => {
  // Tidak perlu menyimpan apa-apa di server, cukup gunakan req.user
  res.json({ userId: req.user.sub, role: req.user.role, msg: 'JWT based profile' });
});

app.listen(3000, () => console.log('Server running on http://localhost:3000'));

Catatan:

  • Untuk produksi, gunakan
    code
    secure: true
    pada cookie, gunakan HTTPS, dan simpan rahasia (
    code
    secret
    ,
    code
    JWT_SECRET
    ) di variabel lingkungan.
  • Jika ingin membatalkan JWT sebelum masa berlaku, pertimbangkan menyimpan daftar token yang telah di‑revoke (misal: di Redis) dan memerikשיה בכל request.

Kesimpulan

Pemilihan antara JWT dan Session tergantung pada arsitektur aplikasi dan kebutuhan operasional Anda:

  • Session lebih cocok bila Anda ingin mengelola logout dengan mudah, memiliki sedikit instance server, dan tidak ingin menambah beban payload pada setiap request.
  • JWT unggul dalam sistem terdistribusi, mikro‑layanan, atau situasi di mana stateless dan skalabilitas adalah prioritas utama, asalkan Anda siap menangani masa berlaku token dan mekanisme pencabutan bila diperlukan.

Kedua pendekatan aman bila diimplementasikan dengan benar—gunakan kunci kriptografi yang kuat, selalu sertakan flag

code
HttpOnly
dan
code
Secure
pada cookie, serta validasi token secara ketat. Dengan memahami trade‑off di atas, Anda dapat membuat keputusan yang tepat untuk menjaga keamanan dan kinerja aplikasi Anda.

*This blog is generated by n8n*

Back to Blog