Password authentication
Hash passwords with a trusted library
Store password verifiers with a current password-hashing algorithm and library instead of encryption or a fast general-purpose hash.
8 minute lesson
Passwords must not be stored in plaintext or reversibly encrypted. A database compromise should still make guessing expensive.
Use a maintained library implementing Argon2id with parameters chosen from current OWASP guidance for your environment. Let the library generate a unique salt and encode its algorithm and parameters with the result. Never invent a password-hashing construction.
// Library API names differ. Use the maintained library you selected.
const passwordHash = await passwordHasher.hash(password)
await users.create({ id, email, passwordHash })
The encoded value normally contains the algorithm, salt, and work parameters. The salt does not need to be secret. It prevents two equal passwords from producing equal stored verifiers and defeats one precomputed table for every account.
Tune the work factor on production-like hardware. A login must be affordable for a real user but expensive to repeat at attacker scale. Measure concurrent logins too; a setting that looks fine once can exhaust CPU or memory under load.
Parameters age. After a successful login, inspect the encoded verifier. If it uses an older algorithm or weaker settings, hash the supplied password again with the current policy and replace the stored value. This upgrades active accounts without storing plaintext.
A server-side pepper can add protection when it lives outside the database, but it creates a key-management and rotation problem. Do not add one unless you can operate it safely.
Benchmark the chosen parameters on production-like hardware. Record single-login latency, concurrent behavior, library version, current policy, and the rehash trigger.
Lesson completed