3 BACKEND API

Authentication (Base)

🔐 Authentication Base: Hashes, Salts, and Sessions

The most dangerous code you will ever write involves User Authentication. If you design a button wrong, the user gets annoyed. If you design Authentication wrong, you will leak 10,000 passwords onto the dark web and destroy your company.

In this lesson, we study the absolute foundational rules of modern password storage: Hashing and Salting.


1️⃣ Rule #1: NEVER Store Plain-Text Passwords

If your database looks like this, you have committed a fireable offense:

idusernamepassword
1adminPassword123
2bobilovedogs

If a hacker exploits a single tiny vulnerability in your Express code (SQL Injection), they download the database table. Because the passwords are raw strings, they instantly log into your users' banking, email, and social media accounts (since people reuse passwords).


2️⃣ The Cryptographic Hash Function

To solve this, we use mathematics. A Hash Function (like SHA-256 or bcrypt) takes an input string and scrambles it into a fixed-length string of garbage.

Input: "hello"
Output (SHA-256): 2CF24DBA5FB0A30E26E83B2AC5B9E29E1B161E5C1FA7425E730...

The Three Laws of Hashing:

  1. Deterministic: Inputting "hello" will always generate the exact same hash.
  2. One-Way (Irreversible): It is mathematically impossible to take the hash and reverse-engineer it back into the word "hello".
  3. Avalanche Effect: Changing "hello" to "hellp" completely destroys the entire output string, making it impossible to guess if two passwords are similar.

The Authentication Flow:

  1. User creates account with password "12345".
  2. Server runs hash("12345") -> abcde99.
  3. Server saves abcde99 to the database. (The server never knows the real password).
  4. User logs in tomorrow and types "12345".
  5. Server hashes their login attempt -> abcde99.
  6. Server checks if abcde99 === abcde99. Access granted.

3️⃣ Breaking Hashes: Rainbow Tables & Salting

Hackers found a way around basic hashing. They generated a "Rainbow Table": a 500GB Excel spreadsheet containing every single word in the dictionary, alongside its pre-computed Hash. When they steal your database, they just run .find() on their spreadsheet to reverse-lookup the hash. If your user's password was "password123", the hacker cracks it in 0.4 seconds.

The Solution: Salting

A Salt is a 20-character string of pure, random gibberish generated uniquely for every single user at the moment they sign up.

  1. User registers: "password123".
  2. Server generates random salt: XyZ!9kP.
  3. Server glues them together: "password123" + "XyZ!9kP".
  4. Server hashes the glued string: 8f7b...

Now, the hacker's 500GB Rainbow Table is completely useless, because the dictionary does not contain the word "password123XyZ!9kP".


4️⃣ Implementing Bcrypt in Express

We do not write cryptography from scratch. We rely on industry-standard libraries like Bcrypt, which automatically handles salting and hashing.

npm install bcrypt

Route 1: Registration

import express from 'express';
import bcrypt from 'bcrypt';

const app = express();
app.use(express.json());

app.post('/api/register', async (req, res) => {
    const { username, plainTextPassword } = req.body;

    try {
        // 1. Define the "cost factor" (How slow the math is). 
        // 10 is standard. By slowing down the CPU, we prevent hackers from 
        // guessing 10 billion combinations a second via brute force.
        const saltRounds = 10;
        
        // 2. Generate the Hash (Bcrypt automatically generates and embeds the Salt inside the hash string)
        const hashedPassword = await bcrypt.hash(plainTextPassword, saltRounds);

        // 3. Save to DB
        await db.users.insert({ username, password: hashedPassword });

        res.status(201).json({ message: "Registered safely!" });
    } catch (err) {
        res.status(500).json({ error: "Server Error" });
    }
});

Route 2: Login

app.post('/api/login', async (req, res) => {
    const { username, plainTextPasswordAttempt } = req.body;

    // 1. Fetch the user's stored hash from the Database
    const user = await db.users.find({ username });
    if (!user) return res.status(404).json({ error: "User not found" });

    // 2. Compare the plain-text attempt against the stored hash
    // Bcrypt automatically extracts the embedded salt, applies it to the attempt, hashes it, and compares.
    const isMatch = await bcrypt.compare(plainTextPasswordAttempt, user.password);

    if (isMatch) {
        // SUCCESS! 
        res.status(200).json({ message: "Logged in!" });
    } else {
        // Never tell the user "Password incorrect", just say "Invalid Credentials" 
        // so hackers don't know if they guessed a valid username or not.
        res.status(401).json({ error: "Invalid Credentials" });
    }
});

💡 Summary Cryptography Rules

TermDefinitionPurpose
Plain-Textmy_dog_123Never store this. A catastrophic security failure.
EncodeBase64Just translating letters to other letters. Hackers can trivially reverse this.
EncryptAES-256Scrambling data with a Master Key. You do this if you need to read the data later (like Credit Cards).
HashSHA-256Irreversibly destroying text into a fingerprint. You do this for Passwords.
SaltRandom garbageAdded before hashing. Defeats Rainbow Table lookup attacks.
BcryptNpm LibraryThe industry standard algorithm that handles salting and slow-hashing automatically.

Knowledge Check

Complete this quick quiz to verify your understanding and unlock the next module.