OAuth 2.0 for Browser-Based Applications

30. 3. 2026

OAuth 2.0 for Browser-Based Applications

30. 3. 2026

Securing Modern Web Apps with a Token-Mediating Backend and Backend-for-Frontend (BFF) Architecture

Authentication in modern web applications is typically built on OAuth 2.0 and OpenID Connect (OIDC), often using a third-party identity provider. These protocols rely on access tokens and (sometimes) refresh tokens — and that creates a hard security problem: If an attacker gets hold of those tokens, they can impersonate the user until the tokens expire (or longer if refresh tokens are reusable). That makes token storage and handling one of the most important design decisions in a browser-based app.

So how do you raise the bar beyond “just implement OAuth correctly”?

The Common Setup: A Browser-Based OAuth 2.0 Client 

Today’s recommended approach for SPAs is Authorization Code flow with PKCE, where the JavaScript application running in the browser behaves as the OAuth client and performs most OAuth responsibilities, including token handling. 

A typical flow looks like this:

  • the browser loads the app from a static web host (A);
  • the app redirects the user to authenticate and receives an authorization code (B);
  • the app exchanges the code for access token (and refresh token) (C);
  • the app stores tokens using browser APIs;
  • app includes access token in requests to resource server (D) and receives responses (E).

When configured correctly, this delivers tokens securely to the browser. The moment the tokens arrive in a JavaScript runtime, however, a new challenge appears: how to store them securely?

Security Considerations: The Browser Is a Hostile Place for Secrets

Modern frameworks help reduce classes of vulnerabilities — but they don’t eliminate them. Browser-based apps remain exposed to:

  • Cross-Site Scripting (XSS) and DOM-based injection;
  • Dependency compromise (supply-chain risk);
  • Malicious browser extensions;
  • Injected scripts via misconfiguration, unsafe third-party tags, or compromised CDNs.

A common (and convenient) practice is storing tokens in Local Storage. Unfortunately, any JavaScript that runs in your origin can read Local Storage, so a single successful injection can exfiltrate tokens instantly.

A Stronger Approach: Delegate Token Management to a Backend

The most effective approach is to keep OAuth tokens off the browser entirely and delegate token management to a trusted back-end component and rely on a secure browser cookie.  This architecture keeps sensitive authentication tokens out of the frontend entirely, shifting the challenge from token protection in JavaScript to the well-understood domain of secure server-managed sessions.

A session cookie configured with:

  • HttpOnly (not readable by JavaScript);
  • Secure (sent only over HTTPS);
  • SameSite (limits cross-site sending);

is dramatically harder to exfiltrate via XSS than Local Storage tokens.

Even though malicious code running in the page may still perform fraudulent actions while the session is active. The key improvement is that the attacker can’t steal reusable tokens for long-term impersonation, and the blast radius is more likely constrained to your site and the user’s active session window.

This approach is commonly implemented using two patterns: Token-Mediating Backend (TMB) and Backend For Frontend (BFF).

Backend for Frontend (BFF)

A BFF is a dedicated backend layer for a specific frontend. It acts as a confidential OAuth client, runs the authorization code flow, stores tokens server-side, and issues only a session cookie to the browser. The frontend always calls the BFF, not the resource servers directly. The BFF attaches access tokens when it calls downstream APIs.

The basic BFF flow:

  • browser loads the app from a static host (A);
  • app checks with the BFF whether a session exists (B);
  • if not, the browser is redirected to BFF (C) to initiate the authorization code flow (D) and returns a code to the BFF (E);
  • the BFF exchanges the code for tokens (server-side) (F);
  • BFF associates tokens with user session, sets a session cookie, and redirects back to the app (G);
  • response triggers app reload (H) and checks for existing session (I) to resume in authenticated state;
  • app calls the BFF with the cookie (J), the BFF calls APIs with the access token (K) and returns results (L).

Although it adds architectural complexity, a Backend-for-Frontend (BFF) significantly strengthens web application security by keeping OAuth tokens off the client entirely. The browser never sees access or refresh tokens and relies solely on an HttpOnly session cookie, which cannot be exfiltrated via XSS. As a result, even if malicious JavaScript executes, it can’t “grab tokens and leave”It can at worst act within the user’s current session. Meanwhile, token refresh and rotation remain on the server, where you can enforce stronger storage controls, auditing, and security policies.

Token-Mediating Backend (TMB)

A Token-Mediating Backend is a lighter approach focused on token exchange and refresh operations. It keeps refresh tokens server-side and uses a session cookie, but unlike a BFF, it typically returns an access token to the browser, and the app calls resource servers directly.

The basic scenario:

  • app checks with the TMB whether a session exists (B);
  • if not, the browser is redirected through the authorization flow and returns a code to the TMB (C, D, E);
  • the TMB exchanges the code for tokens (server-side) (F);
  • TMB associates tokens with user session, sets a session cookie, and redirects back to the app (G);
  • response triggers app reload (H) and checks for existing session (I) to resume in authenticated state and obtains access token;
  • app uses access token to make direct requests to resource server (J).

The token-mediating backend is less robust than a BFF, but it still reduces the worst failure mode of pure in-browser OAuth: long-lived token theft via refresh tokens.

Conclusion

Modern authentication security requires more than just implementing OAuth correctly.It demands thoughtful architecture that prevents token exposure in the first place. By moving token handling to a backend component and using secure, HttpOnly cookies for browser sessions, you significantly reduce the risk of token exfiltration and long-term account compromise,especially compared to storing tokens in Local Storage.

Prefer BFF when you can: it provides the strongest protection against token theft and simplifies secure token lifecycle management. TMB should be only considered when a proxying BFF is impractical (for example, certain network topologies, performance constraints, or legacy API patterns)and even then, treat it as a compromise.

If you want the benefits of these patterns without building everything from scratch, Wren:IG can be used as the backend component to support a BFF-style approach helping you keep tokens off the browser and standardize secure session handling.

Need to improve the security of your apps? Let us do the heavy lifting. Contact us.

Resources: