Autentikasi: Hash Password & Token

Menyimpan password dengan aman (salt + hash), membuat token bertanda tangan, dan melindungi route dengan middleware.

Part 21 dari 24 ± 50 menit Gratis

Autentikasi vs otorisasi

  • Autentikasi: "kamu siapa?" — membuktikan identitas (login).
  • Otorisasi: "kamu boleh melakukan apa?" — hak akses (admin, pengguna biasa).

Aturan emas: jangan simpan password asli

Jika database bocor (dan itu sering terjadi), password asli membahayakan penggunamu di semua situs. Simpan hash: hasil fungsi satu arah yang tak bisa dibalik menjadi password. Saat login, hitung hash dari password yang diketik lalu bandingkan.

  • Hash biasa seperti MD5/SHA-256 saja tidak cukup (terlalu cepat; mudah ditebak dengan tabel pelangi/brute force).
  • Pakai salt: string acak unik per pengguna yang digabung sebelum hashing, sehingga password yang sama menghasilkan hash berbeda.
  • Pakai fungsi hash yang sengaja lambat: bcrypt, scrypt, argon2, atau PBKDF2 dengan iterasi besar.
const crypto = require('crypto');

function hashPassword(password, salt = crypto.randomBytes(8).toString('hex')) {
  const hash = crypto.pbkdf2Sync(password, salt, 1000, 32, 'sha256').toString('hex');
  return { salt, hash };
}

function cekPassword(password, salt, hashTersimpan) {
  const hash = crypto.pbkdf2Sync(password, salt, 1000, 32, 'sha256');
  return crypto.timingSafeEqual(hash, Buffer.from(hashTersimpan, 'hex'));
}

Di kode nyata pakai iterasi jauh lebih besar (mis. ≥ 100.000 untuk PBKDF2) atau pustaka bcrypt/argon2. Angka 1000 di sini hanya agar latihan cepat. timingSafeEqual mencegah serangan yang mengukur waktu perbandingan.

Token: bukti bahwa kamu sudah login

Setelah login berhasil, server memberi klien token. Klien menyertakannya di tiap permintaan berikutnya sehingga server tak perlu meminta password lagi. Bentuk umum: JWT (JSON Web Token): header.payload.tanda-tangan. Payload berisi data (ID pengguna, waktu kedaluwarsa); tanda tangan dibuat dengan kunci rahasia server sehingga tak bisa dipalsukan tanpa kunci itu. (Payload hanya di-encode, bukan dienkripsi: jangan taruh rahasia di dalamnya.)

const SECRET = process.env.TOKEN_SECRET || 'rahasia-kelasit';

function buatToken(payload, detik = 3600) {
  const isi = Buffer.from(JSON.stringify({ ...payload, exp: Date.now() + detik * 1000 })).toString('base64url');
  const ttd = crypto.createHmac('sha256', SECRET).update(isi).digest('base64url');
  return `${isi}.${ttd}`;
}

function bacaToken(token) {
  const [isi, ttd] = String(token).split('.');
  if (!isi || !ttd) return null;
  const benar = crypto.createHmac('sha256', SECRET).update(isi).digest('base64url');
  if (ttd !== benar) return null;                                   // dipalsukan / diubah
  const payload = JSON.parse(Buffer.from(isi, 'base64url').toString());
  return payload.exp > Date.now() ? payload : null;                // kedaluwarsa?
}

Di proyek nyata gunakan pustaka teruji seperti jsonwebtoken atau jose daripada membuat sendiri — contoh di atas menunjukkan prinsipnya.

Middleware pelindung

function wajibLogin(req, res, next) {
  const [skema, token] = (req.get('authorization') || '').split(' ');
  const payload = skema === 'Bearer' ? bacaToken(token) : null;
  if (!payload) return res.status(401).json({ error: 'Token tidak valid' });
  req.user = payload;                  // titipkan untuk handler berikutnya
  next();
}

app.get('/profil', wajibLogin, (req, res) => res.json(req.user));

Klien mengirim header Authorization: Bearer <token>.

Alur lengkap

  1. POST /register — validasi, hash password, simpan { salt, hash } (bukan password).
  2. POST /login — cari pengguna, cocokkan hash; jika cocok balas { token }, jika tidak 401 dengan pesan umum ("email atau password salah" — jangan bocorkan mana yang salah).
  3. Route terlindungi memakai middleware wajibLogin.

Keamanan tambahan

  • Selalu HTTPS di produksi.
  • Kunci rahasia dari variabel lingkungan, bukan dari kode.
  • Batasi percobaan login (rate limit).
  • Token berumur pendek + refresh token untuk aplikasi serius.
  • Jangan mengirim salt/hash ke klien: hapus dari respons.

Praktikkan langsung, gratis

Tulis dan jalankan kode langsung di browser, dapatkan penilaian otomatis. Daftar gratis kapan saja untuk menyimpan progres dan meraih sertifikat.

Coba latihan sekarang, tanpa daftar
Bagikan: WhatsApp Facebook LinkedIn X