Password hashing — Argon2id is the answer, here is how
If you still store passwords, you must hash them with a memory-hard function. Here is how to configure Argon2id correctly in a Node.js or Python backend.
The single most common password-hashing mistake is picking the wrong algorithm. Argon2id is the current OWASP recommendation. Bcrypt is still acceptable but should be migrated. Everything else (MD5, SHA-256, PBKDF2 with too few iterations) is unsafe.
What it is
A password hash converts a password into a verifiable value that cannot be reversed. Memory-hard functions (Argon2id, scrypt, bcrypt) are resistant to GPU + ASIC cracking.
Vulnerable example
// Vulnerable: fast hash + no salt
import { createHash } from "crypto";
const stored = createHash("sha256").update(password).digest("hex");
// An attacker with a GPU rainbow-tables this in hours.Fixed example
// Fixed: Argon2id
import argon2 from "argon2";
// On signup
const hash = await argon2.hash(password, {
type: argon2.argon2id,
memoryCost: 19456, // 19 MiB
timeCost: 2,
parallelism: 1,
});
// On login
const valid = await argon2.verify(hash, passwordInput);How Securie catches it
apps/web/app/api/route.ts:22Password hashing
Securie's crypto specialist flags any password-hashing call-site using MD5, SHA-1, SHA-256/512 (without PBKDF2), or PBKDF2 with too few iterations.
// Fixed: Argon2id
import argon2 from "argon2";
// On signup
const hash = await argon2.hash(password, {
type: argon2.argon2id,
memoryCost: 19456, // 19 MiB
timeCost: 2,
parallelism: 1,
});
// On login
const valid = await argon2.verify(hash, passwordInput);Checklist
- Argon2id with OWASP-recommended parameters
- Salt is random + unique per password (handled by argon2 library)
- Old bcrypt hashes are re-hashed on next login
- No MD5, SHA-1, SHA-256, or plain-sha without PBKDF2
- Password verification is constant-time (handled by library)
FAQ
Should I migrate existing bcrypt hashes?
Yes, but not immediately. On next successful login with the old bcrypt hash, re-hash with Argon2id. Over 6-12 months your entire user table migrates without a lockout event.
Related guides
Row-Level-Security bypass is the most common data leak in vibe-coded apps. Here is exactly how it happens, how attackers find it, and how to fix it in Next.js + Supabase with one policy update.
BOLA is the top item on the OWASP API Security Top 10 for a reason — every AI coding assistant introduces it by default. Learn what it looks like in Next.js, how to exploit it, and how to fix it.
IDOR is the classic name for an authorization bug where a user can change an ID in a URL and access data they should not see. It is BOLA's older cousin and still ships in half of all new apps.
Every week founders tweet about their OpenAI bill going from $10 to $10,000 overnight. Usually the cause is an API key committed to a public repo. Here is why it happens in Next.js specifically and how to stop it in five minutes.