tutorial, express.js,

Autentikasi JWT di Express.js: Login, Token, dan Proteksi Route

Kiki/🎮🍉⌨️🍩💻 Kiki/🎮🍉⌨️🍩💻 Aug 25, 2026 · 9 mins read
Autentikasi JWT di Express.js: Login, Token, dan Proteksi Route
Share this

Hampir setiap API butuh sistem autentikasi — cara untuk memverifikasi identitas pengguna sebelum mengizinkan akses ke resource yang dilindungi. Salah satu pendekatan paling populer untuk API modern adalah JWT (JSON Web Token).

Di artikel ini kita bangun sistem autentikasi lengkap: registrasi, login, dan middleware untuk melindungi route.


Apa itu JWT?

JWT adalah token berbentuk string yang mengandung informasi terenkripsi. Strukturnya terdiri dari tiga bagian yang dipisahkan titik:

header.payload.signature
eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MX0.abc123xyz
  • Header — algoritma enkripsi yang digunakan
  • Payload — data yang disimpan (user ID, role, expiry)
  • Signature — tanda tangan untuk memverifikasi token tidak dimodifikasi

Alur Autentikasi JWT

1. User POST /auth/login dengan email + password
2. Server verifikasi credentials → generate JWT → kirim ke klien
3. Klien simpan JWT (localStorage / cookie)
4. Untuk request berikutnya, klien kirim JWT di header:
   Authorization: Bearer <token>
5. Server verifikasi JWT setiap request ke route yang dilindungi

Setup

npm install express bcryptjs jsonwebtoken
  • bcryptjs — hashing password yang aman
  • jsonwebtoken — generate dan verify JWT

Simulasi Database Pengguna

// data/pengguna.js
const bcrypt = require('bcryptjs');

const pengguna = [];
let idCounter = 1;

module.exports = {
  findByEmail: (email) => pengguna.find(p => p.email === email),
  findById: (id) => pengguna.find(p => p.id === id),
  create: async (data) => {
    const hash = await bcrypt.hash(data.password, 10);
    const baru = { id: idCounter++, nama: data.nama, email: data.email, password: hash };
    pengguna.push(baru);
    return baru;
  }
};

Middleware Autentikasi

// middleware/auth.js
const jwt = require('jsonwebtoken');
const SECRET = process.env.JWT_SECRET || 'rahasia-super-aman';

function authMiddleware(req, res, next) {
  const header = req.headers['authorization'];
  if (!header || !header.startsWith('Bearer ')) {
    return res.status(401).json({ error: 'Token tidak ditemukan' });
  }

  const token = header.split(' ')[1];
  try {
    const decoded = jwt.verify(token, SECRET);
    req.pengguna = decoded;
    next();
  } catch (err) {
    res.status(403).json({ error: 'Token tidak valid atau sudah kadaluarsa' });
  }
}

module.exports = authMiddleware;

Route Autentikasi

// routes/auth.js
const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const db = require('../data/pengguna');

const SECRET = process.env.JWT_SECRET || 'rahasia-super-aman';
const EXPIRES = '7d';

// POST /auth/register
router.post('/register', async (req, res) => {
  const { nama, email, password } = req.body;

  if (!nama || !email || !password) {
    return res.status(422).json({ error: 'Semua field wajib diisi' });
  }
  if (password.length < 8) {
    return res.status(422).json({ error: 'Password minimal 8 karakter' });
  }
  if (db.findByEmail(email)) {
    return res.status(409).json({ error: 'Email sudah terdaftar' });
  }

  const pengguna = await db.create({ nama, email, password });
  const token = jwt.sign({ id: pengguna.id, email: pengguna.email }, SECRET, { expiresIn: EXPIRES });

  res.status(201).json({
    pesan: 'Registrasi berhasil',
    token,
    pengguna: { id: pengguna.id, nama: pengguna.nama, email: pengguna.email }
  });
});

// POST /auth/login
router.post('/login', async (req, res) => {
  const { email, password } = req.body;

  const pengguna = db.findByEmail(email);
  if (!pengguna) {
    return res.status(401).json({ error: 'Email atau password salah' });
  }

  const valid = await bcrypt.compare(password, pengguna.password);
  if (!valid) {
    return res.status(401).json({ error: 'Email atau password salah' });
  }

  const token = jwt.sign({ id: pengguna.id, email: pengguna.email }, SECRET, { expiresIn: EXPIRES });

  res.json({
    pesan: 'Login berhasil',
    token,
    pengguna: { id: pengguna.id, nama: pengguna.nama, email: pengguna.email }
  });
});

module.exports = router;

Proteksi Route

// index.js
const express = require('express');
const app = express();
const auth = require('./middleware/auth');

app.use(express.json());
app.use('/auth', require('./routes/auth'));

// Route publik — siapa saja bisa akses
app.get('/api/artikel', (req, res) => {
  res.json([{ id: 1, judul: 'Artikel Publik' }]);
});

// Route dilindungi — harus login
app.get('/api/profil', auth, (req, res) => {
  res.json({ pesan: 'Ini data pribadi', pengguna: req.pengguna });
});

app.post('/api/artikel', auth, (req, res) => {
  res.status(201).json({ pesan: 'Artikel dibuat oleh', id: req.pengguna.id });
});

app.listen(3000, () => console.log('Server berjalan di port 3000'));

Test dengan curl

# Register
curl -X POST http://localhost:3000/auth/register \
  -H "Content-Type: application/json" \
  -d '{"nama":"Budi","email":"budi@contoh.com","password":"password123"}'

# Login dan simpan token
TOKEN=$(curl -s -X POST http://localhost:3000/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"budi@contoh.com","password":"password123"}' | grep -o '"token":"[^"]*"' | cut -d'"' -f4)

# Akses route dilindungi
curl http://localhost:3000/api/profil \
  -H "Authorization: Bearer $TOKEN"

Best Practices Keamanan JWT

  • Simpan JWT_SECRET di environment variable, jangan hardcode di kode
  • Gunakan expiry yang wajar — 15 menit untuk access token, 7 hari untuk refresh token
  • Jangan simpan data sensitif di payload JWT — payload bisa di-decode siapapun
  • Gunakan HTTPS di production agar token tidak dicuri di jaringan
  • Implementasi refresh token untuk pengalaman pengguna yang lebih baik

Kesimpulan

Dengan jsonwebtoken dan bcryptjs, kamu bisa membangun sistem autentikasi yang solid di Express.js dalam waktu singkat. JWT stateless sehingga cocok untuk API yang di-scale horizontal. Di artikel berikutnya, kita bahas penanganan error dan validasi input yang lebih profesional di Express.js.

Kiki/🎮🍉⌨️🍩💻
Written by Kiki/🎮🍉⌨️🍩💻
hello I'm friend K.