Backend for Frontend (BFF): A Safer Way to Handle OAuth Tokens in Modern Apps

Share this

Modern web apps, especially SPAs, often work directly with OAuth 2.0 or OpenID Connect flows. It looks simple — authenticate the user, grab a token, and call APIs. But under the hood, this setup can be fragile and risky.
Note: This article belongs to Bonus Content section in our Application Security series.

Where do you store the token? What happens when it expires? What if someone steals it via an XSS attack?

That’s where the Backend-for-Frontend (BFF) architecture comes in — a smart pattern that offloads sensitive token handling to a backend layer that’s purpose-built to support your frontend.

In this blog, we’ll explore why the BFF pattern exists, what problems it solves, how it secures your app, and how you can implement it effectively — especially in Spring-based apps.

What is BFF?

Backend-for-Frontend (BFF) is a design pattern where a custom backend sits between your frontend application and external services (APIs, identity providers, etc.).

It acts like your frontend’s bodyguard — intercepting tokens, shielding business logic, and managing user sessions securely.

Unlike traditional backends, the BFF is designed specifically to serve the needs of one frontend. That means:

  • Tailored endpoints
  • Minimal business logic
  • Focused on security, performance, and frontend coordination
Application Security Series
Application Security Series

Why Do SPAs Need a BFF?

SPAs often try to handle OAuth flows entirely in the browser — which creates security challenges:

ProblemWhy it matters
🔓 Token StorageAccess and refresh tokens stored in localStorage are vulnerable to XSS
🧪 Token ExposureTokens are exposed to browser dev tools, network logs, and extensions
🔄 Refresh HandlingRefresh tokens in JS can be leaked or misused
⚙️ Complex Error LogicHandling 401s, retries, and redirects becomes messy

The BFF pattern moves all of this logic server-side, where it’s easier to secure and manage.

How BFF Solves the Problem

With BFF, your frontend never directly touches tokens. Here’s the new flow:

  1. User accesses your SPA
  2. SPA loads from a static host (e.g., S3 or Nginx)
  3. SPA makes a request to the BFF to initiate login
  4. BFF redirects user to the identity provider (IdP)
  5. After successful login, BFF handles token exchange and stores tokens securely in a server session
  6. BFF sets an HTTP-only cookie to maintain the session
  7. All API requests from the SPA go through the BFF, which attaches the access token

Refreshing tokens? BFF takes care of it — safely, silently, and without the browser touching sensitive credentials.

BFF with OAuth 2.0 & OIDC

A typical BFF-based login flow with OIDC looks like this:

[SPA] ---> [BFF] ---> [Authorization Server]
<---(redirects)---
[User Logs In]
---> [BFF receives tokens]
[Stores session]
[SPA] <--- [Sets cookie for session]

From there:

  • SPA makes API calls to the BFF (/api/me, /api/orders, etc.)
  • BFF retrieves tokens from its session store and calls protected resources
  • SPA only deals with session cookies, not tokens

Benefits of Using BFF

Eliminates token exposure in the browser
Supports secure silent refresh without client-side token logic
✅ Works with traditional session management (cookies + CSRF protection)
✅ Enables fine-grained API access control at the backend
✅ Centralizes security enforcement, logging, and error handling

Spring Boot as a BFF

If you’re using Spring Boot or Spring Security, your BFF can be configured like this:

spring:
security:
oauth2:
client:
registration:
myclient:
client-id: your-client-id
client-secret: your-secret
scope: openid, profile, offline_access
provider:
myprovider:
issuer-uri: https://your-idp.com

You can then use OAuth2AuthorizedClientService or OAuth2AuthorizedClientManager to:

  • Store tokens
  • Manage refresh
  • Proxy requests to backend APIs securely

Add a controller like:

@GetMapping("/api/me")
public ResponseEntity<?> userProfile(OAuth2AuthenticationToken auth) {
return ResponseEntity.ok(auth.getPrincipal());
}

When to Use BFF

✅ Your app is an SPA or mobile frontend
✅ You want secure token storage and refresh
✅ You want to avoid exposing access/refresh tokens to JS
✅ You want your auth flow to survive reloads, tab switches, or long inactivity

If you’re building internal tools, partner portals, or customer-facing SPAs, BFF is the safest bet.

Alternatives? Sure, But…

Could you use browser-based OAuth with implicit flows or client-side refresh? Technically, yes — but it’s far harder to get right and far easier to get hacked.

BFF gives you peace of mind — and your users a stable, secure experience.

Conclusion

Modern apps need modern security patterns — and the BFF is one of the best tools in the box. It offloads token logic from the browser, secures your sessions, and sets up your app for long-term reliability.

And most importantly? It removes the burden of fragile token juggling from your frontend — so you can focus on delivering a great user experience.

Check out https://learn.microsoft.com/en-us/azure/architecture/patterns/backends-for-frontends and https://auth0.com/blog/the-backend-for-frontend-pattern-bff/ link for more information on the current topic.

🙋 Have a Question?

Want help implementing a BFF in Spring Boot? Wondering how to retrofit it into an existing SPA? Or deciding whether your app needs this pattern?

Drop a comment — happy to help!

Share this

Leave a comment

Your email address will not be published. Required fields are marked *