Production: security, testing and deployment · Lesson 14 of 18
Authentication basics with crypto
Hash passwords correctly and understand signed tokens without inventing production auth.
Passwords must never be stored as plaintext or with a fast hash such as SHA-256. Use a deliberately slow password KDF such as scrypt, Argon2 or bcrypt with a random salt per user. At login derive again and compare with timingSafeEqual. Then a session or token represents the authenticated identity.
Password + random salt
slow scrypt
salt + derived hash
timing-safe verify
const crypto = require("node:crypto")
const salt = Buffer.from("00112233445566778899aabbccddeeff", "hex") // fixed for this deterministic demo only
const saved = crypto.scryptSync("correct horse", salt, 32)
function verify(password) {
const candidate = crypto.scryptSync(password, salt, 32)
return crypto.timingSafeEqual(saved, candidate)
}
console.log(verify("correct horse"), verify("wrong"))An HMAC-signed token proves a payload was not changed, but it is not encrypted; anyone holding it can read it. Verify signature, expiry, issuer and audience, and pin the algorithm. In production use a reviewed auth or JWT library, or established sessions, rather than an educational mini implementation.
Quick question
Does a signed JWT hide its payload?
Exercise
Write sign(value, secret) using HMAC SHA-256 and valid to compare signatures. Print true false.
Expected output: true false
const crypto = require("node:crypto")
function sign(value, secret) {
}
function valid(value, signature, secret) {
}
const token = sign("user:42", "demo-secret")
console.log(valid("user:42", token, "demo-secret"), valid("user:7", token, "demo-secret"))Learn more from
Played 0 of 2 games
Sign in to save your progress and earn XP.