INTRO
JWT is not authentication - it is a format. The real questions are: how do you revoke access, how do you detect theft, and how much state you are willing to keep on the server. I pick patterns based on threat model and client type, not trends.
Short-lived access tokens
Access JWTs should live minutes, not days. Long-lived JWTs in `localStorage` are XSS-sensitive; `httpOnly` cookies reduce script access but need CSRF strategy for cookie-based APIs.
For SPAs on the same site, BFF (backend-for-frontend) or same-site cookie sessions sometimes simplify more than “pure JWT.”
Refresh token rotation
Store refresh tokens hashed in the database with device metadata. Rotate on each use; if an old refresh appears, revoke the family - possible reuse attack.
Rate-limit refresh endpoints; they are high value.
When opaque server sessions win
First-party web apps with one API often do fine with a session id in a cookie and Redis/DB backing. Revocation is immediate; debugging is easier.
Microservices pushing JWT between services is a different problem - often mTLS or internal identity layers matter more than JWT size.
KEY TAKEAWAYS
“Treat JWT as a transport format; decide storage and revocation explicitly.”
- 02
Keep access tokens short; rotate refresh tokens and detect reuse.
- 03
Do not ignore CSRF when using cookies for APIs.
CONCLUSION
Closing thought
There is no universal “best auth.” There is the smallest design that meets revocation, XSS/CSRF reality, and how many clients you support. Ready to talk scope? Use Contact — or browse Services for fit.
CONTINUE
Related pages
UP NEXT
TanStack Query with the Next.js App Router
How I use React Query in App Router apps without fighting RSC - server components for initial data, client islands for live updates.
Read next article