Securing Your Web Application: A Developer's Checklist
Essential web application security practices covering OWASP top 10, authentication, CORS, CSP headers, and common vulnerabilities every developer should address.
Author
Robert Baker
Published
Read time
2 min read
Security isn’t a feature you add at the end. It’s a practice you embed from day one. Here are the essentials every web application should implement.
Authentication Done Right
Use Established Libraries
Never roll your own authentication. Use battle-tested solutions:
- Lucia — lightweight, framework-agnostic auth library
- Auth.js (NextAuth) — for Next.js applications
- Passport.js — flexible strategy-based auth for Node.js
Password Storage
If you handle passwords, hash them with bcrypt or Argon2. Never use MD5, SHA-1, or unsalted hashes:
import { hash, verify } from "@node-rs/argon2";
const hashed = await hash(password, {
memoryCost: 19456,
timeCost: 2,
outputLen: 32,
parallelism: 1,
});
const isValid = await verify(hashed, candidatePassword);
Session Management
- Set short session lifetimes (15-30 minutes for sensitive apps)
- Rotate session tokens after authentication
- Invalidate sessions on password change
- Use
HttpOnly,Secure, andSameSite=Strictcookie flags
HTTP Security Headers
Add these headers to every response. Most can be set at the CDN or reverse proxy level:
const securityHeaders = {
"Content-Security-Policy":
"default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'",
"X-Content-Type-Options": "nosniff",
"X-Frame-Options": "DENY",
"Referrer-Policy": "strict-origin-when-cross-origin",
"Permissions-Policy": "camera=(), microphone=(), geolocation=()",
"Strict-Transport-Security": "max-age=63072000; includeSubDomains; preload",
};
Content Security Policy (CSP)
CSP is your strongest defense against XSS. Start strict and loosen only as needed. Avoid 'unsafe-eval' and minimize 'unsafe-inline'.
CORS Configuration
Configure CORS explicitly. Never use Access-Control-Allow-Origin: * on authenticated endpoints:
const allowedOrigins = ["https://app.example.com", "https://admin.example.com"];
function corsHeaders(request: Request): Headers {
const origin = request.headers.get("Origin") ?? "";
const headers = new Headers();
if (allowedOrigins.includes(origin)) {
headers.set("Access-Control-Allow-Origin", origin);
headers.set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
headers.set("Access-Control-Allow-Headers", "Content-Type, Authorization");
headers.set("Access-Control-Allow-Credentials", "true");
}
return headers;
}
OWASP Top 10 Quick Reference
The most common vulnerabilities and their mitigations:
- Broken Access Control — Verify permissions on every request, not just in the UI
- Cryptographic Failures — Use TLS everywhere, encrypt sensitive data at rest
- Injection — Use parameterized queries, never interpolate user input into SQL
- Insecure Design — Threat model during design, not after deployment
- Security Misconfiguration — Disable debug endpoints, remove default credentials
- Vulnerable Components — Audit dependencies regularly with
npm auditor Snyk - Authentication Failures — Rate-limit login attempts, enforce strong passwords
- Data Integrity Failures — Verify software updates, use SRI for CDN scripts
- Logging Failures — Log auth events, access control failures, and input validation failures
- SSRF — Validate and sanitize URLs before making server-side requests
Input Validation
Validate on both client and server. The client validation is for UX; the server validation is for security:
import { z } from "zod";
const CreateUserSchema = z.object({
email: z.string().email().max(255),
name: z.string().min(1).max(100).trim(),
role: z.enum(["user", "admin"]),
});
Practical Next Steps
- Run a security header audit at securityheaders.com
- Enable
npm auditor Snyk in your CI pipeline - Add rate limiting to authentication endpoints
- Review your CORS configuration
- Implement CSP headers, even if they start permissive
Security is iterative. Start with these fundamentals and tighten over time.
Share this article
Get expert development help fast
Our engineering team turns complex ideas into production-ready software tailored to your business.
Post essentials
- Published on July 14, 2025 with real-world implementation examples.
- Designed for fast implementation with 2 min read worth of guidance.
- Validated by Robert Baker team.
Expert contributor
Robert Baker
Robert Baker cares deeply about reliable, well-architected solutions. Every guide we publish is battle-tested in real projects before it reaches the blog.
Browse more articlesShare article
Help your peers level up — share this article with colleagues who'd find it useful.
Email this articleContinue leveling up your engineering skills
Dive deeper with related guides chosen to complement this topic and accelerate your next project.
Field-tested TypeScript Best Practices for 2026
Modern TypeScript patterns every developer should know — strict mode, branded types, const assertions, discriminated unions, and more.
Field-tested Choosing the Right Tech Stack for Your Project
A framework for evaluating technologies and making informed stack decisions. Avoid hype-driven development and pick tools that match your actual requirements.
Field-tested Building Design Systems and Component Libraries
How to create reusable UI component libraries that scale across projects. Covers architecture decisions, documentation, testing, and versioning.
Get engineering insights every week
Subscribe for framework updates, architecture patterns, and deep dives tailored to busy engineering teams.
Subscribe to Our Newsletter
Get tech tips, special offers, and updates delivered to your inbox.