In my previous post, we looked at the "Hotel Booking" analogy to understand Access and Refresh tokens. But once you have these tokens, the next question is the most critical: Where do you put them?
If you leave your room key (Access Token) on the sidewalk, anyone can walk in. In the digital world, where you store your tokens determines if your app is a fortress or a screen door.
1. The LocalStorage Trap
Many beginners store tokens in localStorage. It's easy and convenient, but it has a massive flaw: XSS (Cross-Site Scripting).
- The Risk: If an attacker manages to run a tiny bit of JavaScript on your site, they can read everything in your
localStorage. - The Verdict: Great for user preferences (like Dark Mode), but dangerous for tokens.
2. The Gold Standard: HttpOnly Cookies
For the best security, you should store your tokens in HttpOnly Cookies.
- Why it works: These cookies are invisible to JavaScript. Even if an attacker injects a script, they can't "see" or "steal" the token.
- Pro-Tip: Always pair this with the
Secureflag (so it only travels over HTTPS) andSameSite=Strictto prevent CSRF attacks.
3. Refresh Token Rotation
This is the "Secret Sauce" of modern security. Every time a user uses a Refresh Token to get a new Access Token, the server also sends back a brand new Refresh Token and invalidates the old one.
- Why? If a hacker steals a Refresh Token and uses it, the real user's next attempt to use their token will fail. The server sees the old token being reused and instantly kills the entire session for everyone. It's like a self-destruct button for a stolen key.
Summary for the Developer
- Access Tokens: Store in memory or a Secure Cookie. Keep them short-lived.
- Refresh Tokens: Store in an HttpOnly Cookie. Implement rotation.
- The Goal: Make it so that even if one part of your system is compromised, the "damage window" is as small as possible.