February 14 2025
Authentication in SPAs: Why localStorage Is Usually a Bad Idea
How to think about storing credentials in the browser without turning implementation convenience into silent product risk.
Andrews Ribeiro
Founder & Engineer
3 min Intermediate Systems
Track
Senior Frontend Interview Trail
Step 14 / 15
The problem
Some SPA auth implementations follow this path:
- log in
- receive a token
- save the token in
localStorage - send the token on every request
It works.
And because it works easily, it becomes the default in many projects.
The problem is that easy access for your code also means easy access for any script that manages to run on that page.
Mental model
Think about it this way:
the problem with
localStorageis not storing data in the browser. The problem is storing sensitive credentials in a place accessible to page JavaScript.
If there is XSS or a compromised script, the attacker does not need to guess much.
They can simply read the credential.
That increases the blast radius a lot.
Breaking the problem down
localStorage is easy for you and for the attacker
Your app can read it easily.
An injected script can too.
That is the central point.
It is not a matter of taste.
It is a matter of exposure surface.
HttpOnly cookies change the design
When the credential lives in a cookie with HttpOnly, page JavaScript cannot read the value directly.
That does not eliminate all problems.
But it removes an important class of trivial token access.
Of course, other concerns still exist:
SameSiteSecure- CSRF where relevant
- backend authorization
But the exposure design improves.
Not every SPA can follow the same flow in the same way
Architecture matters.
If there is your own backend and session through cookies, the default usually gets better with an HttpOnly cookie.
If the context is different, the conversation changes too.
The mistake is turning implementation convenience into the main security criterion.
”Usually a bad idea” is not the same as “never”
This point matters.
If the requirement is different, a team may accept the trade-off consciously.
But to do that, it needs to answer:
- why is this risk worth it?
- what mitigations exist?
- which alternative was rejected and why?
Without that conversation, localStorage becomes just a shortcut.
Simple example
Imagine a SPA with a JWT stored in localStorage.
Now imagine an XSS issue somewhere in the application or in a loaded library.
The malicious script can:
- read the token
- send it out
- reuse it while it stays valid
If the design uses an HttpOnly cookie, that direct access to the value no longer happens the same way.
That does not make the application magical.
It just reduces one very relevant surface.
Common mistakes
- Defending
localStorageonly because it is easy to program. - Treating “stateless” like it solves security by itself.
- Assuming an
HttpOnlycookie removes every remaining concern. - Discussing storage without talking about XSS and exposure.
- Saying “never use it” without explaining the risk mechanism.
How a senior thinks about it
People with more experience try to leave dogma behind and go back to the right question:
Who can read this credential in this design? If a script is compromised, what is the blast radius?
That makes the conversation more honest.
Because the debate stops being a framework war and becomes risk modeling again.
What the interviewer wants to see
In interviews, this topic measures applied security maturity.
The evaluator wants to see whether you:
- understand the exposure problem to page JavaScript
- compare alternatives with trade-offs
- avoid empty absolutism
- know how to defend a safer default
A strong answer often sounds like this:
I would avoid
localStorageas the default for auth credentials in a SPA because any script running on the page can read that value. When the design allows it, I prefer anHttpOnlycookie to reduce that exposure. It is not thatlocalStorageis magically forbidden forever, but it is usually a worse default from a risk perspective.
localStorageis not bad because it persists. It is bad because it exposes the credential to the page JavaScript environment.
Implementation convenience should rarely be the only thing deciding where your credential lives.
Quick summary
What to keep in your head
- localStorage is convenient to read and write, but that is exactly why it is also easy for malicious scripts to read.
- The main problem is not persistence. It is exposing the credential to the page JavaScript environment.
- An `HttpOnly` cookie is usually a safer default when the application design allows it.
- Usually a bad idea does not mean always forbidden; it means the justification needs to be better than convenience.
Practice checklist
Use this when you answer
- Can I explain why localStorage increases the blast radius of XSS?
- Do I know how to compare localStorage and `HttpOnly` cookies without turning it into dogma?
- Can I say in which kind of architecture this choice matters more?
- Can I explain in interviews why this approach is usually a bad default?
You finished this article
Part of the track: Senior Frontend Interview Trail (14/15)
Share this page
Copy the link manually from the field below.