tutorial

48 Menyimpan dan Mengecek Token JWT

48 Menyimpan dan Mengecek Token JWT

JSON Web Token (JWT) telah menjadi standar de facto dalam otentikasi modern, terutama untuk aplikasi berbasis web dan mobile. Penggunaan JWT memungkinkan kita untuk membuat sistem otentikasi yang bersifat stateless, sehingga server tidak perlu lagi menyimpan sesi (session) pengguna di backend. Namun, masih banyak pertanyaan mendasar di kalangan engineer, khususnya tentang tempat menyimpan token JWT dan cara mengeceknya secara aman. Artikel ini akan membahas tuntas dua aspek kunci tersebut: menyimpan dan memvalidasi JWT, lengkap dengan contoh kode, simulasi arsitektur sederhana, serta beberapa best practices yang patut diikuti.


Apa Itu JWT?

Secara sederhana, JWT adalah string berformat khusus yang terdiri dari tiga bagian utama:

  1. Header
  2. Payload
  3. Signature

JWT dikirimkan ke client setelah user berhasil login, lalu dikirim ulang ke server di setiap request yang membutuhkan otorisasi. JWT tidak hanya efisien, namun juga portable—bisa dibawa di mana saja, kapan saja.

Contoh token JWT:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxMjMsIm5hbWUiOiJKb2huIERvZSJ9.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk

Bagian 1: Menyimpan Token JWT di Client

Penyimpanan token JWT di sisi client bisa menjadi pedang bermata dua. Pilihan penyimpanan yang salah dapat menimbulkan celah keamanan seperti XSS dan CSRF. Ada beberapa opsi utama:

MetodeKelebihanKekurangan
Local StorageImplementasi mudah, akses luasRentan XSS
Session StorageSeperti localStorage, tapi session-basedRentan XSS, hilang saat tab ditutup
Cookie (HTTPOnly)Tidak bisa diakses JS, aman dari XSSRentan CSRF jika tanpa SameSite

Tabel 1: Perbandingan tempat penyimpanan token JWT

Simulasi Penyimpanan JWT di Local Storage

// Setelah login sukses
localStorage.setItem('access_token', jwtToken);

// Mengambil token pada request selanjutnya
const token = localStorage.getItem('access_token');
fetch('/api/resource', {
  headers: {
    'Authorization': `Bearer ${token}`
  }
});

Namun, localStorage sangat rentan terhadap serangan XSS. Jika attacker bisa menanamkan skrip jahat dalam aplikasi, token bisa dicuri dengan mudah.

Cara terbaik untuk kebutuhan keamanan lebih tinggi adalah dengan menyimpan JWT di cookie yang diberi flag HttpOnly dan SameSite.

// Server mengirimkan set-cookie header saat login
Set-Cookie: token=eyJhbGc...; HttpOnly; Secure; SameSite=Strict

Dengan cara ini, token tidak dapat diakses dari JavaScript, sehingga serangan XSS tidak bisa mengambilnya.

Pro Tips:

  • Gunakan SameSite=Strict jika aplikasi tidak perlu berbagi cookie lintas domain.
  • Tambahkan Secure agar cookie hanya terkirim melalui HTTPS.

Bagian 2: Mengecek/Memvalidasi Token JWT di Server

Setelah token JWT disimpan di client, langkah selanjutnya adalah mengecek validitas setiap request yang masuk. Umumnya, proses ini dilakukan dengan middleware di backend. Mari kita bahas pada dua stack: Node.js (Express) dan Go (Golang).

2.1 Cek Token JWT di Node.js/Express

Untuk verifikasi JWT di Express, kita akan memakai library jsonwebtoken.

Middleware Express: authenticateJWT.js

const jwt = require('jsonwebtoken');

function authenticateJWT(req, res, next) {
  const authHeader = req.headers.authorization;

  if (authHeader) {
    // Format: "Bearer <token>"
    const token = authHeader.split(' ')[1];

    jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
      if (err) {
        return res.sendStatus(403); // Forbidden
      }
      req.user = user;
      next();
    });
  } else {
    res.sendStatus(401); // Unauthorized
  }
}

module.exports = authenticateJWT;

Penggunaan Middleware

const express = require('express');
const authenticateJWT = require('./authenticateJWT');

const app = express();

app.get('/api/resource', authenticateJWT, (req, res) => {
  res.json({ message: "Hello, " + req.user.name });
});

2.2 Verifikasi JWT di Golang

Di Golang, biasanya kita menggunakan package github.com/golang-jwt/jwt/v4.

import (
    "github.com/golang-jwt/jwt/v4"
    "net/http"
    "strings"
)

var secretKey = []byte("your-secret-key")

func authMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        authHeader := r.Header.Get("Authorization")
        if authHeader == "" {
            http.Error(w, "missing auth header", http.StatusUnauthorized)
            return
        }

        tokenString := strings.TrimPrefix(authHeader, "Bearer ")
        token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
            return secretKey, nil
        })

        if err != nil || !token.Valid {
            http.Error(w, "invalid token", http.StatusForbidden)
            return
        }
        next.ServeHTTP(w, r)
    })
}

Diagram Alur: Proses Validasi JWT

Mari kita ilustrasikan secara visual alur penyimpanan dan pengecekan token JWT.

sequenceDiagram
    participant Client
    participant Server

    Client->>Server: Login (username, password)
    Server-->>Client: JWT Token (response body / Set-Cookie)
    Note over Client: Simpan token (localStorage/cookie)

    Client->>Server: Request API (Authorization: Bearer)
    Server->>Server: Verifikasi JWT (cek signature & expired)
    alt Valid
      Server-->>Client: Data/Respon Success
    else Tidak Valid
      Server-->>Client: 401/403 Error
    end

Studi Kasus: Client Local Storage VS Cookies

SkenariolocalStorageCookies (HTTPOnly)
Dapat dicuri via XSSYaTidak
Dapat digunakan untuk CSRFTidak (umumnya)Ya (jika tanpa SameSite=Strict)
Dapat diakses JavaScriptYaTidak
Implementasi Safari/AndroidKonsistenKadang masalah di CORS dan domain/subdomain

Best Practices

  1. Gunakan Cookie HTTPOnly jika aplikasi sangat mementingkan keamanan.
  2. Tambahkan mekanisme refresh token terpisah, bukan bagian dari JWT utama.
  3. Pastikan library JWT di server selalu update.
  4. Selalu validasi exp (expired field) pada payload JWT.
  5. Tidak menyimpan data sensitif di payload.
  6. Lakukan revoke dengan menyimpan daftar blacklist di server (opsional, jika perlu session revoke).

Kesimpulan

Menyimpan dan mengecek token JWT bukan sekadar implementasi teknis, namun juga keputusan arsitektural yang sangat mempengaruhi keamanan aplikasi.
Sebelum memilih metode penyimpanan, pahami trade-off antara kemudahan (developer experience) dan keamanan (security risk). Untuk aplikasi skala kecil-menengah, localStorage sering jadi pilihan praktis, tapi untuk aplikasi finansial atau data sensitif, cookie dengan HttpOnly adalah pilihan mutlak.

Selalu evaluasi kembali security landscape aplikasi Anda secara berkala, dan jangan ragu untuk mengadopsi best practices terbaru di dunia otentikasi JWT. Happy coding!

comments powered by Disqus

Topik Terhangat

programming
273
tutorial
140
tips-and-trick
43
jaringan
28
hardware
11
linux
4
kubernetes
1