In a BFF (Backend for Frontend), a small server on your own domain handles OAuth for the SPA. The browser never holds the tokens.
How it works:
- The BFF runs the OAuth login as a confidential client. That means it has a client secret, which a browser app can't keep safe.
- The BFF stores the access and refresh tokens on the server.
- The browser only gets a session cookie with
HttpOnly,SecureandSameSite. - The SPA calls the BFF. The BFF adds the access token and forwards the call to the APIs.
Why guides prefer it:
- An XSS bug can't steal tokens, because JavaScript never sees them.
- Refresh tokens, the long-lived ones, never reach the browser.
- The client secret makes the OAuth client harder to fake.
Costs:
- You run and scale an extra server.
- Every API call takes an extra hop.
- The cookie session needs CSRF protection.
One limit: while an XSS script runs in the page, it can still call the BFF as the user. The BFF stops token theft, not abuse during the attack.
The IETF draft "OAuth 2.0 for Browser-Based Applications" describes the BFF and lighter options. The lightest is an SPA that does PKCE itself and holds tokens in memory, and the draft calls it the least secure.
- A BFF is a server on your domain that runs OAuth and keeps the tokens.
- The browser only holds an
HttpOnly,Secure,SameSitesession cookie. - XSS can't steal tokens or refresh tokens that never reach the browser.
- The costs are an extra server, an extra hop and CSRF protection for the cookie.
- XSS can still act as the user while the attack runs.
Read more
- OAuth 2.0 for Browser-Based Applications (IETF draft) (https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps)datatracker.ietf.org
- Cross-Site Request Forgery Prevention Cheat Sheet (OWASP) (https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html)cheatsheetseries.owasp.org