Aller au contenu principal

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:

  1. Backend receives plain password in HTTP body (only once).
  2. Backend hashes the password with a secure algorithm.
  3. 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:

PartMeaning
$2a$BCrypt algorithm
10$Work factor (cost) — higher = more secure/slower
Next 22 charsSalt
Remaining charsHashed password

6. What Happens at Login (Verification Process)

When a user logs in:

User sends:

username: "jay"
password: "mypassword123"

Backend Steps:

  1. Retrieve user from DB → get hashed password.
  2. Apply BCrypt.verify:
BCrypt.checkpw(plainPassword, storedHash)
  1. 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.