Security

Everything Wrong With How Most Startups Handle Authentication

JWTs in localStorage, 30-day access tokens, no refresh token rotation — the authentication mistakes we see in code reviews weekly, and the implementation that fixes…

admin · April 18, 2026 · 2 min read

Mistake 1: Storing JWTs in localStorage

Every JavaScript XSS vulnerability can read localStorage without any restriction. If an attacker can inject JavaScript into your application — through a dependency, a user-generated content field, or a third-party script — they can steal every JWT in localStorage and impersonate every logged-in user. Fix: access tokens stored in JavaScript memory (React context or Zustand), refresh tokens in httpOnly, SameSite=Strict, Secure cookies that JavaScript cannot read.

Mistake 2: Long-Lived Access Tokens

Access tokens that expire in 7 days or 30 days dramatically extend the window of opportunity after a token is compromised. Fix: 15-minute access token expiry, 7-day refresh token expiry, silent background refresh that transparently extends the session. Compromised access tokens are useless after 15 minutes.

Mistake 3: No Refresh Token Rotation

Without rotation, a stolen refresh token is permanently valid until it expires. Fix: every refresh token use issues a new refresh token and invalidates the previous one. Attempted reuse of an already-used refresh token immediately invalidates the entire token family and logs the user out.

Mistake 4: No Rate Limiting on Authentication Endpoints

Unprotected login and password reset endpoints are open to credential stuffing attacks. Fix: rate limit by IP address and by target username independently. Exponential back-off after 5 failed attempts per username. CAPTCHA after 3 IP-level failures in a 10-minute window.