DevPath · Learn to code ESPTEN

Authentication and security

Web security: OWASP, CORS and best practices

Thinking like an attacker

A published API receives requests from anyone. Assume that every input is hostile until you validate it. The OWASP project maintains the list of the most common risks; these are the basics you must know.

Injection

It happens when user data is interpreted as code/commands. The classic case is SQL injection:

// BAD: the user controls part of the query.
db.query("SELECT * FROM users WHERE name = '" + name + "'");
// If name = "' OR '1'='1", the condition is always true.

// GOOD: parameterized queries. The engine treats the value as data, not code.
db.query("SELECT * FROM users WHERE name = $1", [name]);

The general defense: never build commands by concatenating user text; use parameters, prepared statements or an ORM.

XSS (Cross-Site Scripting)

If you store a comment like <script>stealCookies()</script> and then render it as-is in the HTML, that script runs in other users' browsers. The defense is to escape/sanitize the output (turn < into &lt;, etc.) and, on the client, avoid innerHTML with untrusted data.

Sanitize and validate input

Validate types, lengths and formats on the server (never trust browser validation alone). Reject what doesn't fit and normalize what you accept.

CORS

The browser, due to the same-origin policy, blocks by default a website at https://myapp.com from calling your API at https://api.other.com via fetch. CORS (Cross-Origin Resource Sharing) is the mechanism by which your server explicitly authorizes which origins may call it, through headers like Access-Control-Allow-Origin. It is not a protection against the attacker: it is a permission your API grants to websites from another origin.

Rate limiting

Limiting how many requests a client is allowed per unit of time. It slows down brute force against login and abuse/DoS. Whoever exceeds it gets a 429 Too Many Requests.

Secrets in environment variables

Keys (JWT secret, DB passwords, API keys) are not written in the code nor committed to the repository. They go in environment variables and are read at runtime:

const SECRET = process.env.JWT_SECRET;

HTTPS always

Without HTTPS, tokens and passwords travel in plain text and anyone on the network can read them. In production, all traffic is encrypted with TLS.

Summary of defenses

Risk Defense
Injection Parameterized queries, ORM
XSS Escape/sanitize the output
Credential theft in transit HTTPS/TLS
Brute force Rate limiting + slow hashing
Leaked secrets Environment variables
Cross-origin calls CORS configured on purpose
Put this into practice

DevPath is a hands-on course: you read the theory here; in the app you put it into practice with exercises that really run, offline.

Start free in the app →
← Authorization: require a token and check rolesView the module →