BFF Pattern for Secure Authentication

TL;DR:
Storing tokens in
localStorage
orsessionStorage
exposes your app to XSS and CSRF vulnerabilities. A better approach? Use a Backend-for-Frontend (BFF) with server-side token storage (like Redis) and httpOnly cookies. Secure by design. Scalable by default.
The Problem with Storing JWTs in localStorage/sessionStorage
Modern SPAs (React, Angular, Vue) often use JSON Web Tokens (JWTs) for authentication. The most common pattern?
// Login
localStorage.setItem('access_token', 'eyJhbGciOi...');
// Fetching APIs
fetch('/api/user', {
headers: {
Authorization: `Bearer ${localStorage.getItem('access_token')}`
}
});
While this looks simple and works great for demo apps, it comes with critical security flaws in production.
Vulnerable to XSS
Any JavaScript running on your site—including malicious scripts from a compromised package, CDN, or browser extension—can read from localStorage or sessionStorage. That means your tokens are one XSS attack away from being stolen.No Built-in Expiry Management
Unlike cookies, localStorage does not auto-expire. If a token is leaked, it stays valid until:You explicitly remove it from localStorage
It naturally expires (e.g. 1-hour token)
Your backend implements some manual revocation logic (rare with stateless JWTs)
That's a huge window of opportunity for attackers.
- CSRF Comes Back if You Use Cookies Poorly
Some devs move JWTs into cookies to protect against XSS — good move. But if you're not careful, you're now exposed to Cross-Site Request Forgery (CSRF).
Enter BFF - A Better Pattern
Instead of shipping tokens to the browser, you:
Store them securely on the server (e.g., Redis)
Use a lightweight,
httpOnly
session cookie to identify the user
How the BFF Auth Flow Works
The Backend-for-Frontend (BFF) pattern fixes these issues by never exposing tokens to the frontend.
Here's the step-by-step breakdown:
Login
User submits credentials to the BFF.
BFF verifies credentials, generates access & refresh tokens.
Stores both in Redis.
Sends back a signed
httpOnly
,Secure
,SameSite=Strict
cookie with just a session ID.
API Requests
The browser sends the cookie automatically with each request.
The BFF reads the session ID, fetches tokens from Redis.
It uses the access token to call downstream APIs or services.
Token Refresh
When the access token expires (e.g., after 15 minutes), the BFF uses the refresh token (stored in Redis) to obtain a new access token.
The user experiences no downtime or login prompts.
Logout
Session is deleted from Redis.
Cookies are cleared.
User is instantly logged out on all devices.
Why Redis?
Redis is tailor-made for this setup.
Blazing Fast: Token lookups happen in sub-millisecond time.
Auto-Expiry (TTL): Redis handles token expiration automatically. No manual cleanup required.
Revocability: You can instantly kill sessions by deleting the key.
Resilience: With AOF/RDB, sessions persist across restarts.
Key Security Advantages
Eliminates XSS Attack Surface
No tokens ever touch the browser. Even if your JS is compromised, your tokens are safe.Robust Session Management
Short-lived access tokens (15 mins) for minimal damage if leakedLong-lived refresh tokens (7 days) for better UX
No race conditions or juggling between tokens on the client
Built for Scale
Redis can handle millions of token operations per second.The BFF becomes a single point of control and abstraction, simplifying your microservice interactions.
Instant Logout & Token Revocation
Unlike stateless JWTs, which can’t be revoked once issued, Redis-stored tokens can be nuked in a single command.
The BFF + Redis approach is a great fit if you're building:
A Single Page Application (SPA) using React, Angular, or Vue
A mobile app with concerns around token leakage
A microservices backend, where each API shouldn't handle session cookies directly
A zero-trust environment, where you want the most control over session lifecycle
Final Thoughts
Storing JWTs in localStorage
may be convenient, but it's a security anti-pattern. It opens you up to XSS and provides no reliable way to revoke tokens.
By moving token management server-side with a BFF and Redis, you get:
Stronger security (XSS/CSRF-proof)
Smoother UX (silent refresh, reliable logout)
Better scalability (stateless API, centralized auth)
In today's threat landscape, security should be the default, not an afterthought. BFF is the path forward.
Subscribe to my newsletter
Read articles from Neelesh Roy directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Neelesh Roy
Neelesh Roy
Neelesh is a Senior Frontend Engineer in the insurance technology industry. He specializes in building responsive, reliable, and user-friendly web applications. With years of experience in modern JavaScript frameworks, he cares deeply about clean code, performance, and good user experience. Neelesh enjoys solving complex business problems with simple, practical solutions. He often works closely with designers and backend teams to bring ideas to life. Outside of work, he likes to stay updated with the latest in web development and technology trends.