ReactJS

Securely Storing Tokens in React: Best Practices for Authentication

Jaykrut Kotadiya
Jaykrut KotadiyaOct 3, 2025

Introduction

One of the most overlooked parts of building a React app is token storage. Many developers don’t think twice and simply go with the easy choice:

“Just throw it into LocalStorage, and we’re done.”

It works, it’s persistent, and it survives page reloads. But here's the risk: LocalStorage or SessionStorage tokens are JavaScript-readable. If your application is XSS (Cross-Site Scripting) vulnerable, attackers can inject code and steal them immediately and have complete control over user accounts.

Even with cookies, you're not necessarily safe. With the wrong settings, you're vulnerable to CSRF (Cross-Site Request Forgery), whereby attackers trick users into doing unwanted things when they're logged in.

The impact can be devastating:

  • In fintech apps : stolen money and compromised accounts.
  • In healthcare : leaked medical records.
  • In social platforms : hijacked profiles and identity theft.

So, how do you secure tokens in React without breaking usability? That’s what we’ll uncover in this blog.

Common Storage Options (and Their Risks)

When building authentication in React, one of the first decisions you’ll face is: Where should I store my tokens?.There are three most common options developers use: LocalStorage, SessionStorage, and Cookies.

  1. LocalStorage

This is the most popular method because it’s fast, persistent, and easy to use. Below show examples like:

1localStorage.setItem("token", userToken);


Pros:

  • Dead simple to implement.
  • Data persists even after refreshing or closing the browser.
  • Great for storing non-sensitive data (like UI preferences).

Cons:

  • Tokens here are fully exposed to JavaScript. If your app is vulnerable to XSS (Cross-Site Scripting), a malicious script can instantly read tokens and send them to an attacker.
  • Once stolen, those tokens can be reused indefinitely until they expire or are revoked.
  • Makes your app a big target for token hijacking

  1. SessionStorage

This works just like LocalStorage, except that the data disappears as soon as the tab or browser is closed:

1sessionStorage.setItem("token", userToken);

Some developers prefer this since it reduces long-term risk, but it’s not foolproof.

Props:

  • Data is temporary—cleared once the user closes the browser.
  • Slightly reduces the window of attack compared to LocalStorage.

Cons:

  • It is exposed to JavaScript, so that XSS attacks can steal tokens here too.
  • The tokens don’t persist across tabs, which can annoy users who expect to stay logged in while multitasking.
  • It doesn't solve the root security issue.Tokens are still readable on the client side.

  1. Cookies

Cookies get a bad rap sometimes because of their association with tracking, but when configured properly, they’re the safest place for tokens in modern web apps. Unlike LocalStorage and SessionStorage, cookies support special flags that make them much harder to attack.

Example (server-side setup)


1 res.cookie("refreshToken", token, {
2  httpOnly: true,   // prevents JavaScript access (blocks XSS)
3  secure: true,     // only sent over HTTPS
4  sameSite: "Strict", // prevents CSRF
5});
6


Props:

  • HttpOnly cookies are invisible to JavaScript so it makes them resistant to XSS attacks.
  • Widely supported and reliable for session management.
  • When paired with short-lived access tokens, they provide a strong security model.

Cons:

  • Without the SameSite or CSRF tokens, cookies can be vulnerable to CSRF attacks (Cross-Site Request Forgery).

Best Practices for Secure Token Storage in React

When building secure authentication in React, how you store tokens can make or break your app’s safety. Let’s explore the five golden rules with examples:

1) Store Access Tokens in Memory

Access tokens are short-lived (5-15 minutes) and should stay in memory only-never

LocalStorage or SessionStorage. Storing access tokens in LocalStorage or SessionStorage makes them accessible to malicious scripts if your app suffers an XSS attack. By keeping them in memory, you limit exposure


1// React state for storing access token
2const [accessToken, setAccessToken] = useState(null);
3

Security Benefit:

Tokens in memory aren’t exposed to XSS, making them much harder for attackers to steal.

2) Keep Refresh Tokens in HttpOnly Cookies

Refresh tokens live longer. They should be hidden from JavaScript using HttpOnly cookies.The safest place is inside an HttpOnly cookie with additional security flags.

1// Express.js example
2res.cookie("refreshToken", token, {
3  httpOnly: true,   // blocks JavaScript access
4  secure: true,     // only sent over HTTPS
5  sameSite: "Strict" // prevents CSRF
6});
7

Security Benefit:

HttpOnly cookies prevent JavaScript access, while cookie flags add extra protection against

CSRF attacks.

3) Use Short-Lived Tokens

Tokens should never last too long. Instead of issuing access tokens that live for hours or days, keep them short—like 5–15 minutes.

If a hacker manages to steal an access token, the damage window is small. Short-lived tokens force attackers to act quickly, reducing the risk of long-term misuse. Meanwhile, users won’t even notice this if you use refresh tokens to silently renew sessions in the background.

Security Benefit:

Even if a token is stolen, its short lifespan minimizes potential damage.

4) Rotate Refresh Tokens

Every time a refresh token is used, issue a new one and invalidate the old one.so If an attacker attacks then they won’t be able to use it after it’s rotated. It protects your app against replay attacks and ensures only the latest refresh token is valid.


1// On refresh request, issue new refresh token
2const newRefresh = jwt.sign({ userId }, REFRESH_SECRET, { expiresIn: "7d" });
3res.cookie("refreshToken", newRefresh, { httpOnly: true, secure: true });
4

Security Benefit:

Stolen refresh tokens become useless once rotated, shutting down replay attacks.

5) Always Use HTTPS

Tokens should never travel over plain HTTP. So always use HTTPS for your frontend and backend communication.Without the HTTPS, anyone on the same network (like in a café Wi-Fi) can intercept requests and steal tokens using simple tools. HTTPS encrypts all traffic, protecting tokens during transmission and keeping attackers out.


1https://yourapp.com/api/login

Security Benefit:

HTTPS encrypts traffic, preventing attackers from sniffing tokens on shared or public networks.


Conclusion

Safe storage of tokens in React is not a technicality.It's an essential aspect of securing your app and users. LocalStorage or SessionStorage may be convenient.The more secure option is to store access tokens in memory, refresh tokens in HttpOnly cookies, and ensure all communications are over HTTPS.

For the best practices-short-lived tokens, token rotation, and secure cookies—you earn the trust of your users and safeguard their data from basic attacks. A bit of additional attention to token management today will keep you out of large security issues tomorrow, while providing your users with assurance that their data is secure.


© 2026 IGNEK. All rights reserved.

Ignek on LinkedInIgnek on InstagramIgnek on FacebookIgnek on YouTubeIgnek on X