Rangkuman praktik terbaik autentikasi dan otorisasi yang harus kamu terapkan di setiap aplikasi.
1. Password yang aman:
// Validasi password yang baik:
function validatePassword(password) {
const errors = [];
if (password.length < 12) errors.push("Minimal 12 karakter");
if (!/[A-Z]/.test(password)) errors.push("Minimal 1 huruf besar");
if (!/[0-9]/.test(password)) errors.push("Minimal 1 angka");
if (!/[^A-Za-z0-9]/.test(password)) errors.push("Minimal 1 karakter spesial");
// Cek terhadap daftar password yang sering dipakai
const common = ["password123", "12345678", "qwerty123"];
if (common.includes(password.toLowerCase())) {
errors.push("Password terlalu umum");
}
return { valid: errors.length === 0, errors };
}
- Hash dengan bcrypt/Argon2 (cost factor 12+)
- Jangan batasi panjang maksimal password (biarkan sampai 128+ karakter)
- Cek terhadap database password yang bocor (Have I Been Pwned API)
2. Proteksi brute force:
const rateLimit = require("express-rate-limit");
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 menit
max: 5, // max 5 percobaan
message: "Terlalu banyak percobaan login. Coba lagi dalam 15 menit.",
keyGenerator: (req) => req.body.email // rate limit per email
});
app.post("/login", loginLimiter, loginHandler);
Tambahan: implementasi account lockout setelah N kali gagal. Kirim notifikasi email.
3. Token management:
// Jangan simpan di localStorage (rentan XSS)!
// Pilihan yang lebih aman:
// A. HttpOnly cookie (untuk web)
res.cookie("token", jwt, {
httpOnly: true, // JS tidak bisa akses
secure: true, // hanya HTTPS
sameSite: "strict",
maxAge: 900000 // 15 menit
});
// B. In-memory (untuk SPA)
// Simpan di variable JavaScript — hilang saat refresh
// Gunakan refresh token di HttpOnly cookie untuk mendapatkan token baru
4. Secure session management:
- Regenerate session ID setelah login (cegah session fixation)
- Set timeout idle session (15-30 menit untuk app sensitif)
- Hapus session saat logout (server-side, bukan hanya hapus cookie)
- Tampilkan "active sessions" agar user bisa revoke
5. Error messages yang aman:
// ❌ Buruk — memberitahu attacker info yang ada
"Email tidak terdaftar"
"Password salah"
// ✅ Baik — tidak membocorkan info
"Email atau password salah"
6. HTTPS everywhere:
- Redirect HTTP ke HTTPS
- Set HSTS header:
Strict-Transport-Security: max-age=31536000; includeSubDomains - Gunakan secure flag untuk semua cookies
7. Logging dan monitoring:
// Log semua aktivitas auth:
logger.info("Login success", { userId: user.id, ip: req.ip });
logger.warn("Login failed", { email: req.body.email, ip: req.ip });
logger.alert("Account locked", { userId: user.id, attempts: 5 });
logger.alert("MFA failed 3x", { userId: user.id });
Checklist keamanan auth:
- Password di-hash dengan bcrypt/Argon2
- Rate limiting pada endpoint login
- CSRF protection pada form dan cookie
- Secure cookie flags (HttpOnly, Secure, SameSite)
- Token expiry yang pendek + refresh token rotation
- Input validation dan sanitization
- Error messages yang tidak bocorkan informasi
- Logging semua aktivitas auth
- MFA tersedia untuk user (wajib untuk admin)
- Regular security audit dan dependency update