Security  

How to Store JWT Token Securely in LocalStorage vs Cookies

Introduction

JSON Web Tokens (JWT) are widely used for authentication in modern web applications. They help verify user identity without storing session data on the server. But a common question among developers is: “Where should I store my JWT token — in localStorage or in cookies?”

This guide will explain both approaches in simple words, discuss their security implications, and help you choose the best method for your Next.js, React, Angular, or Node.js app. You’ll also see examples and best practices for keeping JWTs safe from attacks.

What is a JWT Token?

A JWT (JSON Web Token) is a compact, secure way to represent user data between a client and server. After a user logs in, the server generates a token that contains encoded information like:

{
  "userId": "12345",
  "email": "[email protected]",
  "role": "admin"
}

This token is signed using a secret key, ensuring its authenticity. The client stores this token and includes it with every request to prove the user’s identity.

Example of a JWT

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjM0NSIsImVtYWlsIjoiZXhhbXBsZUBkb21haW4uY29tIn0.uKkhH8QNUZKJfRHF1a_jkXfVZhEN9eCMo64hO_xXYYA

Now, let’s explore where and how to store it securely.

Option 1. Storing JWT in localStorage

What is localStorage?

localStorage is a built-in browser storage system that stores key-value pairs on the client side. Data saved here persists even after refreshing or closing the browser.

Example

// Store token
localStorage.setItem('token', jwtToken);

// Retrieve token
const token = localStorage.getItem('token');

✅ Advantages of Using localStorage

  1. Easy to Use – Simple JavaScript API for storing and retrieving tokens.

  2. Persistent Storage – Tokens stay in the browser even after the page reloads or browser restarts.

  3. Framework Independent – Works with any front-end framework like React, Angular, or Vue.

⚠️ Disadvantages of localStorage

  1. Vulnerable to XSS (Cross-Site Scripting) – If an attacker injects JavaScript into your website, they can easily read the JWT from localStorage.

  2. No Built-In Expiry – You must manually handle token expiration.

  3. Not Automatically Sent to Server – You need to manually attach the token in the request headers:

axios.get('/api/profile', {
  headers: {
    Authorization: `Bearer ${localStorage.getItem('token')}`
  }
});

🛡️ Security Tips for localStorage

  • Use strong Content Security Policy (CSP) to prevent XSS.

  • Avoid storing sensitive data (like passwords or secrets) in the token.

  • Always sanitize user input to block malicious scripts.

  • Consider rotating JWTs regularly and using short expiration times.

Option 2. Storing JWT in Cookies

What Are Cookies?

Cookies are small pieces of data that a server sends to a user's browser. They are automatically included with every HTTP request made to the server.

Example of setting a cookie:

res.cookie('token', jwtToken, {
  httpOnly: true,
  secure: true,
  sameSite: 'Strict',
  maxAge: 3600000 // 1 hour
});

✅ Advantages of Using Cookies

  1. More Secure (when HttpOnly) – Cookies can be marked HttpOnly, preventing JavaScript access and reducing XSS risk.

  2. Automatic Transmission – The browser automatically sends cookies with every request to the same domain.

  3. Built-In Expiry – You can control how long a cookie stays valid.

⚠️ Disadvantages of Cookies

  1. Vulnerable to CSRF (Cross-Site Request Forgery) – Since cookies are automatically sent with requests, an attacker can trick users into making unintended requests.

  2. Limited Storage – Cookies can only store up to 4KB of data.

  3. CORS Configuration Required – When using cookies across different domains, you need to configure CORS properly.

Example of enabling credentials in Express

app.use(cors({
  origin: 'https://yourdomain.com',
  credentials: true
}));

And in frontend (React/Next.js)

axios.get('https://yourdomain.com/api/profile', { withCredentials: true });

🛡️ Security Tips for Cookies

  • Always use HttpOnly and Secure flags.

  • Set SameSite to Strict or Lax to prevent CSRF attacks.

  • Use CSRF tokens if handling sensitive actions.

  • Use HTTPS for all API calls.

localStorage vs Cookies: Comparison Table

FeaturelocalStorageCookies
Ease of UseEasy to implementRequires configuration
PersistencePersists after refreshPersists based on expiry
Automatic Transmission❌ No✅ Yes
XSS Protection❌ Vulnerable✅ Safer (with HttpOnly)
CSRF Protection✅ Safe❌ Needs protection
Storage Limit5-10 MB4 KB
Access from JS✅ Yes❌ No (if HttpOnly)

Best Practice: Use Cookies with HttpOnly + CSRF Tokens

If you’re building a secure web application (like banking, e-commerce, or admin dashboards), the safest approach is to store JWT in HttpOnly cookies. This prevents JavaScript from accessing the token, reducing XSS risks.

To protect against CSRF attacks, you can use a CSRF token that’s sent as a header with every request.

Example

// Backend sets CSRF token
res.cookie('csrfToken', generateToken(), { httpOnly: false, secure: true });

// Frontend sends CSRF token in request header
axios.post('/api/update', data, {
  headers: { 'X-CSRF-Token': csrfToken }
});

This ensures that both XSS and CSRF are handled safely.

When to Use localStorage

Use localStorage if:

  • You’re building a public or low-risk application.

  • Your app doesn’t perform highly sensitive actions (like payments).

  • You can manage security (CSP + short-lived tokens).

Example

localStorage.setItem('token', jwtToken);
axios.get('/api/profile', {
  headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }
});

When to Use Cookies

Use cookies if

  • You’re handling user authentication or sensitive data.

  • You need automatic token transmission with each request.

  • You can implement CSRF protection.

Example

res.cookie('token', jwtToken, {
  httpOnly: true,
  secure: true,
  sameSite: 'Strict'
});

Summary

Choosing between localStorage and cookies for storing JWT depends on your application’s security needs.

  • localStorage is simple and ideal for lightweight or non-sensitive apps but vulnerable to XSS.

  • Cookies (with HttpOnly + Secure) offer better protection against XSS but need CSRF defense.

For maximum security in 2025 and beyond, use HttpOnly cookies with CSRF protection. This method ensures your tokens are stored safely and transmitted securely.