Customer Identity · public betaBuild your first Test integration.Create a Test project
NamoID
All posts
NamoID Blog

BFF vs SPA OAuth: Which Architecture Is Safer?

Compare backend-for-frontend and browser-only SPA OAuth architectures across token exposure, cookies, CSRF, XSS, refresh, and deployment cost.

A backend-for-frontend (BFF) usually offers a stronger security boundary for a browser application because OAuth tokens stay on a server and the browser receives an HttpOnly session cookie. A browser-only single-page application (SPA) can still use OAuth securely, but tokens execute in the same hostile environment as every script loaded into the page.

That does not make the BFF automatically safe. It trades browser token exposure for cookie, cross-site request forgery (CSRF), proxy, and server-operation responsibilities. The right choice depends on the application’s risk, architecture, and ability to run a backend.

The two architectures differ at the trust boundary

In a browser-only SPA, JavaScript performs the Authorization Code flow with Proof Key for Code Exchange (PKCE), receives tokens, and calls APIs directly.

Browser SPA -> authorization server
Browser SPA <- authorization code
Browser SPA -> token endpoint with PKCE verifier
Browser SPA <- access token
Browser SPA -> resource API

In a BFF, the browser starts the flow, but a server component exchanges the code, stores tokens, and proxies or mediates API calls.

Browser -> BFF -> authorization server
Browser <- session cookie <- BFF
Browser -> BFF -> resource API
                 access token stays server-side

The difference is not whether OAuth exists. It is where the tokens live and which component is trusted to use them.

BFF reduces direct token exposure

An HttpOnly cookie cannot be read through ordinary browser JavaScript. That means a cross-site scripting (XSS) payload cannot simply read an access or refresh token and send it elsewhere.

The protection has limits. Malicious JavaScript running in the application origin may still issue requests through the victim’s authenticated BFF session. The attacker may be unable to steal the credential, but can sometimes act while the compromised page remains open.

A BFF therefore reduces token exfiltration risk; it does not remove the need for output encoding, a restrictive Content Security Policy, dependency hygiene, and authorization at the API.

SPA keeps infrastructure smaller

A browser-only SPA can call an authorization server and API without operating a token-handling backend. This can be appropriate when:

  • the client is genuinely public;
  • the API accepts tokens from browser clients;
  • the requested privileges are limited;
  • access tokens are short-lived;
  • refresh behavior follows current guidance; and
  • the team accepts the browser’s exposure model.

PKCE is mandatory for this design. It protects the authorization code from interception, but it does not protect a token after malicious JavaScript obtains it. The PKCE explainer covers that boundary.

Avoid persistent browser storage for bearer tokens where possible. Values in localStorage are directly readable by JavaScript on the origin and can outlive the tab that created them.

Once the browser uses a session cookie, every state-changing endpoint must consider CSRF. A BFF should combine appropriate SameSite cookie policy with an anti-CSRF mechanism suitable for the deployment. Do not assume SameSite alone covers every browser, redirect, subdomain, and integration pattern.

The session cookie should be:

  • HttpOnly;
  • Secure in production;
  • narrowly scoped by domain and path;
  • assigned an intentional SameSite policy; and
  • rotated or invalidated when the session changes materially.

The BFF must also validate redirect targets, bind login state to the initiating browser, and prevent an attacker from completing their own authorization flow inside a victim’s session.

BFF becomes a security-sensitive proxy

A naive proxy that accepts any destination or forwards every header creates a server-side request forgery and credential-leak risk.

Use a fixed upstream allowlist. Build outbound requests from known routes, strip untrusted forwarding headers, validate methods and content types, cap body sizes, and ensure an access token is sent only to its intended audience.

If the BFF serves several resource APIs, maintain separate token and audience rules. One token should not be forwarded merely because two APIs share a hostname suffix.

Refresh and logout differ

An SPA must decide whether it can refresh without a long-lived browser credential. Refresh-token rotation and reuse detection reduce replay risk but do not make an extracted refresh token harmless. The authorization server and application must also handle concurrent requests and the response to detected reuse.

A BFF can store refresh tokens server-side and expose only a session identifier to the browser. That improves containment, but the server now owns encrypted storage, rotation races, revocation, session expiry, and cleanup.

The refresh-token rotation guide explains the replay model. Logout in either architecture should end the local session and, where required, coordinate authorization-server logout or token revocation without relying on the browser to delete one value.

Compare the trade-offs directly

QuestionBrowser-only SPABFF
Token locationBrowser runtimeServer-side
Token exfiltration through XSSHigher exposureReduced direct exposure
Action through active XSSPossibleStill possible through session
CSRF responsibilityLower for header bearer tokensExplicit cookie protection required
Backend operationsMinimalRequired
API integrationBrowser calls APIBFF mediates or proxies
Refresh-token storageBrowser riskServer storage and rotation complexity
Best fitLower-risk public-client applicationsSensitive applications able to run a backend

Choose based on risk, not fashion

Use a BFF when the application handles sensitive actions, can operate a backend, and benefits materially from keeping tokens out of browser JavaScript. Use a browser-only SPA when the application is truly static, privileges are constrained, and the team can follow the public-client security profile without pretending the browser is confidential.

The IETF’s OAuth guidance for browser-based applications analyzes these patterns and their threats. It remains important to check the document’s current publication status rather than treating an Internet-Draft as a final RFC.

NamoID uses Authorization Code with PKCE for browser authorization. Teams still choose how their application handles its own session and API boundary. Read the hosted versus embedded authentication guide, then start with NamoID’s developer resources.