How Passwords Are Handled (Backend, Security, Hashing, Verification)
This file explains everything that happens to a password in a secure authentication system—what the frontend does, what the backend stores, how hashing works, and how Spring verifies passwords.
1. IMPORTANT RULE
A password is NEVER stored in plain text.
Not in:
- frontend
- backend
- database
- logs
- console
Passwords must always be hashed before being stored.
2. What the Frontend Does With Passwords
✔️ Only sends password once: at login or registration
Example request:
POST /api/auth/login
{
"username": "jay",
"password": "mySecret123!"
}
❌ The frontend should never store:
- plain password
- a transformed password
- a derived hash
After sending the login request, the password disappears from memory.
3. What the Backend Does When Creating a User
When a new user registers:
- Backend receives plain password in HTTP body (only once).
- Backend hashes the password with a secure algorithm.
- Backend stores the hash (not the password) in the database.
Example:
Password received: "myPassword123!"
Password stored in DB: "$2a$10$9SYT8swaeU14kxZ2ZpA4uuxPft8Q2Bi4N..."
The original password cannot be retrieved.
4. Password Hashing: Key Security Concepts
A secure backend (like Spring Security) uses:
✔️ A one-way hash function
You can only hash, not unhash.
✔️ A unique salt
- A random value added to each password before hashing
- Prevents identical passwords from producing identical hashes
- Prevents rainbow table attacks
Spring Security automatically handles salts.
✔️ Multiple iterations
- Hashing the password thousands of times
- Makes brute-force attacks slower and harder
BCrypt uses adaptive cost factor.
5. The Hash Algorithm Used in Spring Boot: BCrypt
Spring uses BCrypt by default:
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
A BCrypt hash looks like this:
$2a$10$9SYT8swaeU14kxZ2ZpA4uuxPft8Q2Bi4N5K3nhuGbVvG6vZeyFe2
Breakdown:
| Part | Meaning |
|---|---|
$2a$ | BCrypt algorithm |
10$ | Work factor (cost) — higher = more secure/slower |
| Next 22 chars | Salt |
| Remaining chars | Hashed password |
6. What Happens at Login (Verification Process)
When a user logs in:
User sends:
username: "jay"
password: "mypassword123"
Backend Steps:
- Retrieve user from DB → get hashed password.
- Apply BCrypt.verify:
BCrypt.checkpw(plainPassword, storedHash)
- BCrypt:
- extracts salt from stored hash
- rehashes the password with the same salt
- compares the result
✔️ If match → login success
❌ If mismatch → 401 Unauthorized
Important:
The backend never needs to decrypt the stored password—it simply re-hashes and checks whether the result matches.
7. Why Hashing Protects Users
If someone steals your database:
They CANNOT read the passwords
Only see hashes.
They CANNOT reverse the hash
Mathematically impossible.
They CANNOT reuse rainbow tables
Because BCrypt uses a unique salt for every password.
It would take:
- years per password, even with powerful GPUs
- and BCrypt can be configured to be slower as machines get faster
8. Best Practices (followed by Spring)
✔️ Never write your own crypto
✔️ Always use BCryptPasswordEncoder
✔️ Never lower the BCrypt cost factor
✔️ Never store plain passwords in logs or exceptions
✔️ Always enforce HTTPS in production
✔️ Never expose password hashes in API responses
✔️ Never accept weak passwords (optionally add validation rules)
9. Example Flow in Spring Boot (Realistic Scenario)
Registration
User:
POST /auth/register
{
"username": "jay",
"password": "strongPassword!"
}
Backend:
Hash password with BCrypt -> store hashed password
Save user -> return 201 Created
Stored in DB:
{
"username": "jay",
"password": "$2a$10$8Ks...6yExO"
}
Login
User:
POST /auth/login
{
"username": "jay",
"password": "strongPassword!"
}
Backend:
Take stored hash from DB
Use BCrypt.checkpw()
If valid → generate JWT token
Return { token, user }
10. Common Questions
Can the backend ever know the user's real password?
No. It receives it once and never stores it.
Can we “decrypt” a hashed password?
No. Hashing is one-way.
Why not store passwords in plain text?
Because if the database is leaked → users' accounts everywhere are compromised.
Is JWT responsible for password hashing?
No. JWT = authentication after login.
BCrypt = password protection before login.
Separate roles.
Should JWTs contain passwords?
Absolutely not.
Never put sensitive data inside a JWT.
JWTs contain only non-sensitive identifiers like:
{ "userId": 42, "roles": ["USER"] }
Summary
- Frontend sends password → backend hashes with BCrypt
- Stored password is a hash with salt
- Login compares hashes, never decrypts
- Passwords always remain unreadable
- JWT is issued after password is verified
- JWT never contains the password
This is the modern, secure way all professional apps handle authentication.