Phase 4 · Authentication & SecurityModule 29~64 min read

API Hardening: Validation, Headers, CORS & CSRF

Harden Express input and browser boundaries with allowlists, parameterized queries, Helmet, precise CORS, CSRF defenses, and safe output.

What you'll learn

Harden the API where untrusted data and browser behavior enter the system. Apply allowlist validation, safe query construction, security headers, precise CORS, and CSRF protection appropriate to the credential model.

By the end of this lesson, you'll be able to:

  • Validate every request location
  • Prevent injection and unsafe output
  • Configure headers and CORS narrowly
  • Defend cookie-authenticated mutations from CSRF

Core mental model

Node.js becomes easier when you separate the JavaScript language from the runtime and the operating-system capabilities it exposes. Use this table as a decision guide.

ConceptWhat it meansDecision rule
AllowlistA closed set of accepted shapes and valuesReject unknown fields and normalize only after validation
CORSA browser read-permission policyTreat it as browser isolation, never authentication
CSRFCross-site use of ambient credentialsProtect state changes when cookies are sent automatically

Professional workflow

Build and verify Node.js programs from the terminal in small, observable steps.

  1. Define the HTTP security boundary boundary: inputs, outputs, invariants, ownership, and expected failures.
  2. Design the data or message contract before choosing implementation details.
  3. Implement the smallest correct path with dependencies passed explicitly.
  4. Add validation, failure translation, cleanup, and concurrency behavior.
  5. Verify the boundary with realistic data and at least one adversarial case.
  6. Measure or observe the behavior before optimizing or extracting abstractions.

Keep the feedback loop short

Run the smallest useful command after every meaningful change. Read the complete error message before editing again, and keep inputs and outputs visible while you learn.

Guided code lab

Compose a hardened browser boundary

Security headers, a fixed origin allowlist, bounded JSON, and explicit CSRF verification each solve a different risk.

security.js
app.disable('x-powered-by');
app.use(helmet());
app.use(express.json({ limit: '32kb', type: 'application/json' }));
app.use(cors({
  origin: ['https://app.example.test'],
  credentials: true,
  methods: ['GET', 'POST', 'PATCH', 'DELETE'],
}));
app.use('/api', verifyCsrfForUnsafeMethods);

Production practice

Contract

Each route defines body, parameter, query, content-type, size, authentication, authorization, and response schemas.

Verification

Fuzz unknown fields, oversized bodies, SQL/meta operators, hostile origins, preflight behavior, missing CSRF tokens, and unsafe redirects.

Operations

Log validation categories rather than secrets, monitor rejection spikes, and review browser policies as clients change.

Common failure mode

CORS does not stop curl, mobile clients, or servers. It controls whether browser JavaScript may read responses.

Independent workshop

Create a reusable security pipeline for all task API routes.

Your finished workshop must include:

  • Request schemas
  • Size/content limits
  • Parameterized data access
  • Helmet policy
  • Origin allowlist
  • CSRF tests

Definition of done

Run the happy path and at least two edge cases, keep responsibilities separated, and add a short README explaining how to run the program.

Recap & quick check

Key takeaways

  • Validate at boundaries
  • CORS is not auth
  • Cookies create CSRF risk
  • Headers reduce browser attack surface
  • Output needs a contract

Quick check

1. What does CORS authorize?

2. When is CSRF central?

3. How should dynamic sort fields work?

Next: Rate Limits, Secrets & Supply-Chain Security