DEV Community

Cover image for Stop Storing Tokens in localStorage
Mahdi Hosseini
Mahdi Hosseini

Posted on

Stop Storing Tokens in localStorage

A Better Way to Handle Authentication in Frontend Applications πŸ”

Modern frontend applications are becoming more complex every day.
But one mistake still appears in many production apps:

Storing authentication tokens directly in localStorage.

At first, it feels simple and practical.
But as your app grows, this approach can become a serious security risk.


The Problem With localStorage

A lot of developers do this after login:

localStorage.setItem("token", accessToken);
Enter fullscreen mode Exit fullscreen mode

Simple, right?

The issue is that anything stored in localStorage is accessible through JavaScript.

That means if your application ever suffers from an XSS attack, malicious scripts can instantly steal your users’ tokens.

And once a token is stolen:

  • User sessions can be hijacked
  • Accounts can be accessed
  • Sensitive data can leak

The bigger your product becomes, the more dangerous this gets.


Common Mistakes Developers Make ❌

1. Storing Tokens in localStorage

localStorage.setItem("token", token);
Enter fullscreen mode Exit fullscreen mode

Problem:

  • Accessible via JavaScript
  • Vulnerable to XSS attacks

2. Using Cookies Without Security Flags

document.cookie = `token=${token}`;
Enter fullscreen mode Exit fullscreen mode

Problem:

  • Missing HttpOnly
  • Missing Secure
  • Missing SameSite

Without proper flags, cookies can become another attack vector.


3. Long-Lived Access Tokens

Many apps create tokens that live for days or even months.

Problem:

  • If leaked, attackers keep access for a long time
  • Harder to revoke securely

The Better Architecture βœ…

A much safer authentication flow looks like this:

Access Token β†’ Store in Memory

Keep access tokens only in:

  • React state
  • Context API
  • Zustand / Redux memory store

Example:

const [token, setToken] = useState(null);
Enter fullscreen mode Exit fullscreen mode

Why?

  • Not persisted permanently
  • Cleared on refresh
  • Much smaller attack surface

Refresh Token β†’ Store in HttpOnly Cookie

The refresh token should be stored by the server using:

Set-Cookie:
refreshToken=abc123;
HttpOnly;
Secure;
SameSite=Strict;
Enter fullscreen mode Exit fullscreen mode

Why this is safer:

  • JavaScript cannot access it
  • Helps protect against XSS
  • More secure session management

Recommended Authentication Flow πŸ”„

Step 1 β€” User Logs In

User sends credentials to the server.


Step 2 β€” Server Responds

Server returns:

  • Short-lived access token
  • HttpOnly refresh token cookie

Step 3 β€” Frontend Stores Access Token in Memory

setAccessToken(token);
Enter fullscreen mode Exit fullscreen mode

Used only for API requests.


Step 4 β€” Token Expires

Frontend silently requests a new access token using the refresh token cookie.

No need to expose sensitive data to JavaScript.


Why This Architecture Scales Better πŸš€

As applications grow:

  • Security becomes more important
  • Teams become larger
  • APIs become more complex
  • Risks increase

Good architecture is not just about β€œmaking it work.”

It’s about:

  • Scalability
  • Maintainability
  • Security
  • Long-term stability

Security Checklist βœ…

Before shipping authentication to production:

  • Use HTTPS everywhere
  • Keep access tokens short-lived
  • Store refresh tokens in HttpOnly cookies
  • Never hardcode tokens
  • Sanitize user input
  • Protect against XSS
  • Rotate refresh tokens
  • Handle logout properly
  • Monitor token expiration

Final Thoughts

Frontend security is often ignored until something breaks.

But small architectural decisions today can prevent massive security problems tomorrow.

Clean code matters.
Scalable architecture matters.
But secure authentication matters even more πŸ”

If you're building modern frontend applications with React or Next.js, investing time into secure token handling is absolutely worth it.


Top comments (0)