Almost every application eventually needs to answer a simple question:
When you sign in, the experience looks simple: Username or email + password → Log in. Behind that form is a chain of security decisions involving the user's device, the Internet, backend servers, databases, cryptography, and application architecture.
To understand password authentication, start with a deliberately bad system: What would happen if we built login with no security at all?
01 · START WITH THE PROBLEM
The Simplest Possible Login System
Imagine Alice creates an account. Her browser sends a login request, and the backend compares the supplied password with a value in its database.
POST /login
{
"email": "alice@example.com",
"password": "MyPassword123"
}email password
-----------------------------------------
alice@example.com MyPassword123
bob@example.com SuperSecret456Functionally, this works. From a security perspective, it is terrible. We must think about the entire journey of the password—not only the comparison at the end.
There are security risks while the password travels and after it reaches the database.
02 · PROBLEM: DATA IN TRANSIT
The Password Travels Across the Internet
If login information travels over ordinary HTTP, sensitive data may be exposed to someone able to observe or manipulate traffic along an insecure path. That is one reason modern applications use HTTPS.
HTTPS is HTTP protected with TLS—Transport Layer Security. TLS encrypts communication between client and server and helps the client authenticate the server. An observer should not simply be able to read Alice's credentials from network traffic.
The database remains a major risk. If it contains plaintext passwords and an attacker obtains a copy, every user's password is exposed. The consequences may reach other services because people frequently reuse passwords.
A properly designed application should not store users' plaintext passwords.
REAL-WORLD SECURITY FAILURE
The 2017 Equifax Data Breach
In 2017, Equifax suffered one of the largest data breaches in U.S. history, affecting roughly 147 million people. According to the U.S. Federal Trade Commission, it did not begin with plaintext passwords—attackers first exploited an unpatched vulnerability in a web application.
Once inside the network, they found an unsecured file containing administrative credentials stored in plaintext. Those credentials helped them reach additional systems and large amounts of sensitive consumer data. The FTC also cited inadequate network segmentation and intrusion detection.
SECURITY IS ABOUT LAYERS
This is defense in depth: no single control protects an entire system. HTTPS protects data in transit. Password hashing protects stored passwords if the database is exposed. Access controls limit what authenticated users can reach. Network segmentation slows an attacker moving between systems. Monitoring helps detect suspicious activity. Each layer covers what the others miss.
Source: U.S. Federal Trade Commission — Equifax settlement03 · DATA AT REST
What Is a Hash?
A cryptographic hash function takes an input and produces a fixed-size output. Change the input—even by one character—and a well-designed cryptographic hash produces a dramatically different result. This is associated with the avalanche effect.
"MyPassword123" → HASH FUNCTION → Result A
"MyPassword124" → HASH FUNCTION → Result BENCRYPTION · REVERSIBLE
PASSWORD HASHING · ONE WAY
Encryption is designed to be reversible when you possess the right key. Password hashing is intentionally one-way. The system does not need to recover your password; it only needs to determine whether you entered the same password.
Determinism
The same input produces the same output.
Preimage resistance
Given a hash, recovering a corresponding input should be computationally infeasible.
Second-preimage resistance
Given one input, finding another with the same hash should be difficult.
Collision resistance
Finding any two different inputs with the same hash should be difficult.
Avalanche behavior
A small input change produces a dramatically different output.
At a simplified level, write a hash function as H(x) = y. Computing y from x should be efficient. Given only y, finding an x that produces it should be computationally difficult.
04 · SECURE COMPARISON
How Login Works With Password Hashing
At registration, the backend runs the password through a password-hashing algorithm and stores the encoded result—not the original password.
email password_hash
-------------------------------------------------
alice@example.com $argon2id$...
bob@example.com $argon2id$...When Alice returns, the backend retrieves her stored representation and asks the password-hashing library to verify the candidate password against it.
05 · OFFLINE ATTACKS
One-Way Doesn't Mean Passwords Can't Be Cracked
An attacker usually does not need to mathematically reverse a hash. They can guess passwords, hash each candidate, and test for a match. Weak passwords can still be discovered.
password
123456
qwerty
letmein
summer2026
...A random salt prevents identical passwords from producing identical stored results and defeats reusable precomputed lookup tables.
ALICE
MyPassword123 + random-A
→ unique hash A
BOB
MyPassword123 + random-B
→ unique hash B
Salts do not need to be secret. They are stored alongside the hash, and modern password-hashing libraries normally generate and manage them automatically.
06 · CHOOSE THE RIGHT TOOL
Why SHA-256 Isn't Enough for Passwords
SHA-256 remains useful for many cryptographic applications, but SHA256(password) is not a good password-storage design. SHA-256 is intentionally fast—and speed helps attackers test more guesses.
Password hashing should be deliberately expensive. Modern choices include Argon2id, scrypt, bcrypt, and PBKDF2. OWASP recommends Argon2id when available, scrypt as an alternative, bcrypt mainly for legacy situations, and PBKDF2 where FIPS-validated implementations are required.
Read the OWASP Password Storage Cheat Sheet07 · FROM EXPERIENCE
A Real Engineering Problem I Encountered at POLITICO
Early in my career, while working at POLITICO, I was involved in migrating users from an older ColdFusion system to a newer Java backend. Existing users needed to keep signing in with their current passwords.
“Just move the passwords” was not an option. A properly designed system has password hashes, not plaintext passwords. The new application needed to reproduce a compatible verification process.
OLD SYSTEM
ColdFusion
Algorithm · salt · encoding · parameters
NEW SYSTEM
Java
Compatible password verification
The programming language was not the important part. Different languages can produce compatible results when they implement the same underlying transformation: algorithm, salt, encoding, work factor, parameters, and representation.
I learned the approach from other engineers. The experience stayed with me because frameworks and languages change, but the fundamental concepts remain.
Migrating old algorithms today
If a legacy application uses an old scheme and the new application uses Argon2id, compatibility should not preserve weaker protection forever. One common strategy upgrades the hash after a successful login.
The system upgrades each returning user after the old password has been verified—without ever recovering plaintext passwords.
Users who never return may require a password reset or another migration strategy. This is the difference between knowing how hashing works and making an engineering decision about a production system.
08 · IMPLEMENTATION
Password Hashing in Python
A modern Python application can use Argon2id through the argon2-cffi library. The library manages salts and encodes the algorithm, parameters, salt, and hash into the stored value.
from argon2 import PasswordHasher
from argon2.exceptions import VerifyMismatchError
ph = PasswordHasher()
password = "MyPassword123"
# Registration: hash the password
password_hash = ph.hash(password)
print(password_hash)$argon2id$v=19$m=65536,t=3,p=4$...entered_password = "MyPassword123"
try:
ph.verify(password_hash, entered_password)
print("Login successful")
except VerifyMismatchError:
print("Invalid password")There is no password decryption step. Verification determines whether the entered password corresponds to the stored representation.
09 · PUTTING IT TOGETHER
The Engineering Lesson
INSECURE DESIGN
BETTER BASIC DESIGN
HTTPS protects credentials in transit. Password hashing protects passwords at rest from direct disclosure if the database is exposed. But authentication does not end there.
After password verification, the application must maintain a session. That leads to cookies, access tokens, JWTs, OAuth, OpenID Connect, social sign-in, and multi-factor authentication. Then comes another essential distinction: authentication tells us who you are; authorization decides what you can do.
AI can generate a login endpoint in seconds. An engineer still needs to ask how the password is transmitted and stored, which algorithm and parameters are appropriate, what happens after compromise, and how the design can be upgraded later.
Build something real. Understand how it works.