Security
Web Security and Authentication: A Developer's Guide
Web Security and Authentication: A Developer's Guide
Quick answer: Web security for developers centers on a small set of recurring concerns: verifying who a user is (authentication), controlling what they're allowed to do (authorization), protecting data in transit and storage, and defending against a known set of common attacks (like XSS and SQL injection). Most real-world breaches come from skipping these basics, not from exotic attacks.
Authentication vs Authorization
These two terms get confused constantly, but they answer different questions:
| | Question it answers | Example | |---|---|---| | Authentication | Who are you? | Logging in with email/password | | Authorization | What are you allowed to do? | Only admins can delete users |
Full breakdown: Authentication vs Authorization
How JWT Authentication Works
JSON Web Tokens (JWT) are a common way to handle authentication in REST APIs:
const jwt = require("jsonwebtoken");
// After verifying email/password on login:
const token = jwt.sign(
{ userId: user._id, role: user.role },
process.env.JWT_SECRET,
{ expiresIn: "7d" }
);
res.json({ token });
// Middleware to protect routes
function requireAuth(req, res, next) {
const token = req.headers.authorization?.split(" ")[1];
if (!token) return res.status(401).json({ error: "No token provided" });
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = decoded;
next();
} catch {
res.status(401).json({ error: "Invalid or expired token" });
}
}
app.get("/api/profile", requireAuth, (req, res) => {
res.json({ userId: req.user.userId });
});
The token is issued once at login and sent by the client on every subsequent request, letting the server verify identity without a database lookup on every call. Full guide: What Is JWT and How Does JWT Authentication Work?
Never Store Passwords in Plain Text
const bcrypt = require("bcrypt");
// When a user signs up
const hashedPassword = await bcrypt.hash(plainPassword, 10);
await User.create({ email, password: hashedPassword });
// When a user logs in
const isMatch = await bcrypt.compare(plainPassword, user.password);
Hashing is one-way — even if your database is ever exposed, attackers can't reverse a properly hashed password back to the original. Full guide: How to Store Passwords Safely
Common Vulnerabilities to Know
| Vulnerability | What it is | Basic defense |
|---|---|---|
| SQL Injection | Malicious input alters a database query | Parameterized queries / an ORM |
| XSS (Cross-Site Scripting) | Malicious scripts injected into pages | Escape/sanitize user input before rendering |
| CSRF (Cross-Site Request Forgery) | Tricking a logged-in user's browser into unwanted actions | CSRF tokens, SameSite cookies |
These map directly to entries in the OWASP Top 10, the industry-standard list of the most critical web security risks. Full breakdown: Common Web Security Vulnerabilities
Securing a REST API in Practice
app.post("/api/orders", requireAuth, async (req, res) => {
const { productId, quantity } = req.body;
if (!productId || typeof quantity !== "number" || quantity <= 0) {
return res.status(400).json({ error: "Invalid order data" });
}
const order = await Order.create({
userId: req.user.userId, // never trust a userId sent from the client
productId,
quantity,
});
res.status(201).json(order);
});
Note that userId comes from the verified token, not from the request body — trusting client-supplied identity fields is a common and dangerous mistake. Full guide: How to Secure a REST API
Common Mistakes Developers Make
- Storing JWT secrets or database passwords directly in source code instead of environment variables.
- Trusting user-supplied IDs (
userId,role) from the request body instead of the verified token. - Not setting token expiration, so a stolen token remains valid forever.
- Returning detailed error messages (stack traces, database errors) directly to API clients.
Best Practices
- Hash passwords with
bcrypt(orargon2); never store or log plain-text passwords. - Keep JWT expiration short and use refresh tokens for longer sessions where needed.
- Validate and sanitize all user input on the server — never trust the frontend alone.
- Use HTTPS everywhere; never transmit credentials or tokens over plain HTTP.
- Keep dependencies updated — many real-world breaches exploit known vulnerabilities in outdated packages.
FAQs
What's the difference between session-based and token-based authentication? Session-based auth stores login state on the server and references it with a cookie; token-based auth (like JWT) encodes identity directly in a token the client holds. See Session-Based vs Token-Based Authentication for a full comparison.
Is JWT the best authentication method? It's a good default for stateless REST APIs, but not universally "best" — session-based auth is still a reasonable, often simpler choice for traditional server-rendered apps.
Do small projects really need to worry about security? Yes — many real breaches target small, poorly secured apps precisely because they're easier targets, not because attackers only go after large companies.
What is OWASP? A nonprofit organization that publishes widely referenced security resources, most notably the OWASP Top 10 list of critical web application risks. See What Is OWASP?
How do I know if my API is secure enough? Start with the basics covered here — authentication, authorization checks on every route, input validation, and hashed passwords — then consider a dedicated security review or automated scanning tool as the application grows.
Should secrets like API keys ever be in frontend code? No — anything shipped to the browser is visible to users. Secrets belong on the server, accessed through environment variables, never in client-side JavaScript.
Conclusion
Most real-world security problems come from skipping a small number of well-known basics: hash passwords, validate all input, never trust client-supplied identity, and keep secrets out of source code. Get these right consistently, and you've addressed the majority of real-world risk before touching anything more advanced.
Related Articles
- What Is JWT and How Does JWT Authentication Work?
- Authentication vs Authorization
- How to Secure a REST API
- Common Web Security Vulnerabilities
CTA
Building an app that handles user accounts or payments? Get in touch — secure authentication is built into projects like VertexCRM.
Image Plan
Image 01 — Featured image Type: Technical illustration Prompt: "Minimalist illustration of a padlock icon over a code window, dark navy and red accent color, clean white background, premium tech editorial style" Filename: web-security-best-practices-hardik-yadav.webp Alt: "Illustration representing web security and authentication for developers" Ratio: 16:9 Source: AI-generated
Image 02 — After JWT code example Type: Diagram Prompt: "Flat sequence diagram showing a user logging in, receiving a JWT token, and sending it back on future requests to a protected route, minimal labeled arrows" Filename: jwt-authentication-flow-diagram.webp Alt: "Diagram of the JWT authentication flow" Ratio: 16:9 Source: Diagram (self-made/AI-generated)
Image 03 — After vulnerabilities table Type: Diagram Prompt: "Flat illustration of three labeled shield icons representing defenses against SQL injection, XSS, and CSRF, minimal clean style" Filename: web-security-vulnerabilities-defense-diagram.webp Alt: "Diagram of common web security vulnerabilities and their defenses" Ratio: 4:3 Source: Diagram (self-made/AI-generated)
