Safeguard
Security Guides•

Where should a single page app keep its OAuth tokens?

Tokens in localStorage can be read by any script on your origin. RFC 10017 ranks three patterns, and a backend for frontend is the strongest. Here is how to choose.

Safeguard Security Team
4 min read

The strongest place is not the browser at all. RFC 10017, the IETF best current practice for browser based OAuth apps, ranks a backend for frontend (BFF) first: the server holds the tokens and the browser holds only a session cookie. If you must keep tokens in the browser, accept the risk knowingly.

The three patterns

RFC 10017, published in August 2026, lists three architectures in decreasing order of security.

PatternWho holds tokensTrade off
Backend for frontend (BFF)The BFF server, tied to a cookie sessionMore to build and run
Token mediating backendBackend gets tokens, hands access token to the appStolen access token still works
Browser based OAuth clientThe browser app itselfSimplest, most exposed

What a BFF does

The RFC gives the BFF three jobs. It acts as a confidential OAuth client toward the authorization server. It manages access and refresh tokens inside a cookie based session, so no token is exposed to the browser app. It forwards API requests to the resource server and adds the right access token on the way.

Because the tokens never reach the browser, a script injected into your page has no token to steal. The RFC says the BFF pattern is strongly recommended for business applications, sensitive applications, and applications that handle personal data.

It is not free. The RFC admits the BFF is significantly more complicated than a browser only app, and that proxying every API call adds load to server components.

Why not just use localStorage

The RFC is direct: localStorage does not protect against unauthorized access from malicious JavaScript, because the attacker's code runs in the same origin and can read the contents. It also persists across tabs and sessions, so a stolen refresh token can work for a long time. The RFC notes sessionStorage is tied to one tab, which slightly reduces exposure, and also describes in memory storage as an option. Neither removes the risk.

A decision guide

  1. Do you control a server that can sit in front of your APIs? Build a BFF.
  2. Do you handle personal or financial data? Treat the BFF as the default, per the RFC.
  3. No backend and no way to add one? Use the authorization code flow with PKCE, short lived access tokens, and refresh token rotation. Keep tokens in memory where you can, and accept that an XSS bug can still reach them.
  4. Whatever you pick, work on XSS prevention. A strict Content Security Policy and output encoding reduce the chance an attacker runs code in your origin.

Cookie settings for the BFF session

Because the BFF relies on a cookie session, treat that cookie as the crown jewel. Use the Secure and HttpOnly attributes and choose a SameSite value deliberately. The RFC also discusses server side versus client side sessions: server side sessions give you control and revocation, while signed client side sessions are easier to scale but harder to revoke.

Quick check

Is an HttpOnly cookie safer than localStorage for a session?

For reading the value, yes: scripts cannot read an HttpOnly cookie. But a script in your origin can still make requests that carry the cookie, so XSS remains a serious problem.

Does a BFF replace the need for PKCE?

No. RFC 9700 recommends PKCE even for confidential clients, and a BFF is a confidential client.

Safeguard's SBOM and dependency scanning shows which front end and auth libraries you ship and which have known advisories. There is a free scan if you want to try it on a repo.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.