Skip to main content
Security

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, and SameSite=Strict cookie 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:

  1. Broken Access Control — Verify permissions on every request, not just in the UI
  2. Cryptographic Failures — Use TLS everywhere, encrypt sensitive data at rest
  3. Injection — Use parameterized queries, never interpolate user input into SQL
  4. Insecure Design — Threat model during design, not after deployment
  5. Security Misconfiguration — Disable debug endpoints, remove default credentials
  6. Vulnerable Components — Audit dependencies regularly with npm audit or Snyk
  7. Authentication Failures — Rate-limit login attempts, enforce strong passwords
  8. Data Integrity Failures — Verify software updates, use SRI for CDN scripts
  9. Logging Failures — Log auth events, access control failures, and input validation failures
  10. 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

  1. Run a security header audit at securityheaders.com
  2. Enable npm audit or Snyk in your CI pipeline
  3. Add rate limiting to authentication endpoints
  4. Review your CORS configuration
  5. Implement CSP headers, even if they start permissive

Security is iterative. Start with these fundamentals and tighten over time.

Get a security review for your application →

Topics covered SecurityOWASPAuthenticationWeb DevelopmentBest Practices
Need dev help?

Get expert development help fast

Our engineering team turns complex ideas into production-ready software tailored to your business.

Book a consult
Next up

Continue leveling up your engineering skills

Dive deeper with related guides chosen to complement this topic and accelerate your next project.

Stay connected

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.