Content
The single worst mistake in authentication is storing plaintext passwords. Yet tutorials still do it because it is simpler to demonstrate. The moment your database leaks—and databases do leak—every user's password is exposed. Worse, because people reuse passwords, the breach spreads to their email, banking, and social accounts.
The fix is hashing, but not just any hash. Use a slow, password-specific algorithm: bcrypt, scrypt, or Argon2. A common tutorial error is reaching for SHA-256. SHA-256 is designed to be fast. A modern GPU can compute billions of SHA-256 hashes per second, making offline cracking trivial. Password hashing algorithms are deliberately slow to make each guess expensive.
Two more details tutorials frequently miss: salt and constant-time comparison. Every password should be hashed with a unique random salt, so two users with the same password get different hashes. And when comparing hashes, use a constant-time function like hmac.compare_digest rather than ==. String comparison short-circuits on the first differing byte, leaking timing information that can be exploited.
Session Management: Cookies Are Not Enough
Once a user logs in, you need to remember them. Tutorials often set a session cookie with the user ID and call it done. That approach invites session fixation, cross-site scripting theft, and cross-site request forgery.
Regenerate the session ID on login. If an attacker plants a known session ID before you authenticate, and you keep that same ID afterward, they now share your session. Regenerating the ID on successful login discards the attacker's pre-login identifier.
Set the right cookie flags. A session cookie should have HttpOnly (blocks JavaScript access), Secure (transmits only over HTTPS), and SameSite (mitigates CSRF). Tutorials rarely mention these because they do not affect functionality—only security.
Store only an opaque identifier in the cookie. Do not put user data, roles, or email addresses in the session cookie itself. Keep sensitive data server-side and give the client a meaningless token that maps to it.
Login Throttling: The Missing Defense
Nothing stops an attacker from automating login attempts against your form unless you stop them. Tutorials almost never include rate limiting, leaving a wide-open door for brute-force and credential-stuffing attacks.
Implement per-IP and per-account throttling. A common pattern is to allow a small number of failed attempts—say five—before introducing a delay or temporary lockout. The lockout should be finite: fifteen minutes is typical, with an option to reset the password to regain access immediately.
Return generic error messages. Saying "wrong password" versus "no account with that email" tells an attacker which usernames exist. Use a single message like "Invalid credentials" for all failures. Even the response time should be consistent; if checking a non-existent user returns instantly while checking a real user takes 200 milliseconds for hash verification, you have a timing-based enumeration vulnerability.
Account Recovery: The Weakest Link
Password reset flows are where security often collapses. A poorly designed recovery mechanism can bypass every other protection you built.
Never use security questions as the sole recovery method. Answers are guessable or discoverable through social media. OWASP explicitly advises against them.
Generate cryptographically secure reset tokens. The token should be long, random, single-use, stored hashed in your database, and expire within 15 to 60 minutes. Do not email the user a new password directly—send a reset link that lets them choose one.
Keep the response generic. Whether the email exists or not, show the same message: "If an account exists for that address, we have sent a reset link." This prevents enumeration through the recovery flow.
Multi-Factor Authentication: More Than a Buzzword
MFA adds a second proof of identity beyond the password. The most common forms are TOTP (time-based one-time passwords from apps like Google Authenticator) and hardware keys like FIDO2. SMS-based MFA exists but is no longer recommended due to SIM-swapping and interception risks.
Tutorials often skip MFA entirely because it adds complexity. But the security gain is substantial: even if an attacker steals a password through phishing or a breach, they cannot log in without the second factor.
The critical detail tutorials miss is recovery. If a user loses their phone or hardware key, they need a way back in. Provide single-use recovery codes at enrollment, and communicate clearly that these codes must be stored safely. Without a recovery path, users will abandon MFA—or your service.