Module Recap
Module 06 secured the Bulletin API. Users can now register and log in; protected routes know who’s making each request; and the server is hardened against common attacks.
What you learned
Section titled “What you learned”Authentication and authorization are distinct. Authentication answers “who are you?” — verified by credentials. Authorization answers “what can you do?” — enforced in route logic. 401 means unauthenticated; 403 means authenticated but forbidden.
bcrypt hashes passwords one-way. Never store plain text. bcrypt.hash() produces a 60-character hash from a password; bcrypt.compare() verifies without reversing. Salt rounds control computational cost — 12 is a good default.
JWTs are self-contained identity tokens. Signed with a secret key that only the server knows. jwt.sign() creates a token; jwt.verify() validates it or throws. The payload carries userId and username — no database lookup needed per request.
The authenticate middleware is the gatekeeper. It reads Authorization: Bearer <token>, verifies the JWT, and attaches the payload to res.locals.user. Apply it per-route where authentication is required.
CORS, Helmet, and rate limiting harden the API. CORS controls which origins can call the API. Helmet adds security headers with one line. Rate limiting prevents brute-force attacks — stricter limits on auth endpoints.
The Bulletin auth system
Section titled “The Bulletin auth system”POST /auth/register body: { username, password } → bcrypt.hash(password, 12) → password_hash → INSERT INTO users → jwt.sign({ userId, username }) → token → return { token, userId, username }
POST /auth/login body: { username, password } → SELECT user by username → bcrypt.compare(password, user.password_hash) → jwt.sign({ userId, username }) → token → return { token, userId, username }
POST /posts (protected) header: Authorization: Bearer <token> → authenticate middleware: jwt.verify(token) → payload → res.locals.user = { userId, username } → controller: INSERT INTO posts (... user_id = res.locals.user.userId)Key terms
Section titled “Key terms”| Term | What it means |
|---|---|
| Authentication | Verifying identity — who are you? |
| Authorization | Controlling access — what can you do? |
| 401 | Unauthenticated — no valid token |
| 403 | Unauthorized — valid token, but not allowed |
| bcrypt | One-way password hashing algorithm |
| Salt rounds | bcrypt cost factor — higher = slower = more secure |
| JWT | JSON Web Token — signed, self-contained identity assertion |
jwt.sign(payload, secret) | Creates a token |
jwt.verify(token, secret) | Validates a token or throws |
res.locals.user | Request-scoped authenticated user data |
| CORS | Allows cross-origin requests from specified origins |
| Helmet | Sets security headers (one line) |
| Rate limiting | Throttles requests to prevent abuse |
What is next
Section titled “What is next”Module 07 — Bulletin API Build →
Module 07 assembles everything into the complete Bulletin backend. You’ll design the final schema, build user registration and login, implement posts and comments endpoints, and deploy the API to Railway. By the end, you’ll have a live, working backend that the React frontend will connect to in Part 2.