📊 We use cookies & analytics to improve your experience. Learn more
Latest

Full-Stack Web Development Bootcamp Module 5 · Lesson 14 of 15

0% Exit to course

Module 5 · Testing, security and shipping Lesson 14 of 15

Security basics every full-stack app needs

Learning objective

A handful of habits cover most of the risk: validate everything the client sends, never trust the client for permissions, set a few safe headers, and rate-limit the login.

The concept

Never build a query by joining strings - parameterised queries are what stop injection, and they cost nothing to use from the start.

Return the smallest error you can: a message that says whether an email exists helps an attacker and helps nobody else. "Invalid email or password" for both cases is the safe answer.

JavaScript
import helmet from 'helmet';
import rateLimit from 'express-rate-limit';

app.use(helmet());                     // sensible security headers

const loginLimit = rateLimit({ windowMs: 60_000, max: 5 });
app.post('/api/login', loginLimit, loginHandler);

// parameterised query - never string-joined
const rows = await db.query(
  'SELECT id, password_hash FROM users WHERE email = ?',
  [email]
);

Worked example

A rate limit of five login attempts a minute turns a password-guessing script into a slow, detectable trickle instead of a crash test.

Your practice task

Add input validation, a rate limit on login and three security headers to your API, then note what each one prevents.

Do this before moving on. Reading a solution teaches the shape of it; typing it teaches you.

Key takeaway

Never build a query by joining strings - parameterised queries are what stop injection, and they cost nothing to use from the start.

Create free account or sign in

Almost there

15 lessons left of 15

Finish every lesson to unlock the certificate. Each one ends in a practice task — do them and the final project brief writes itself.

Next recommended course Data Analytics with SQL & Excel