The world of web development has changed a lot in the last decade. We’ve moved from traditional, multi-page websites that build pages on a server, to single-page applications (SPAs), which have become a popular way to build websites. While old-school sites need to reload the entire page for every user action, causing noticeable delays, SPAs feel more fluid and app-like. They use JavaScript to update content dynamically without reloading the page. This shift has been helped by powerful JavaScript frameworks like React, Angular, and Vue, which give developers great tools to build complex, interactive apps. However, this approach, where most of the work happens in your browser, also creates unique security challenges.

Traditional websites often start with an HTML template. The server then requests the necessary user-specific data and generates the HTML page, incorporating the retrieved data and user-specific information into the template. This is often done using server-side languages like PHP, Python, or Java. In SPAs, however, all the code to update the page runs directly in your browser. The client-side logic, written in JavaScript, will typically call APIs that return the dynamic content. The problem is that these APIs aren’t usually open to everyone; they need some form of authorisation.
In this article, we’ll focus on the security issues of using the OAuth2 standard in SPAs, as it’s one of the most common ways to authorise APIs today.
OAuth2 security in single-page applications
The first problem with OAuth2 security for SPAs is with client (application) authentication. In short, an SPA shouldn’t have any secret keys or passwords stored in its code, because anyone can see them in their browser. This means the OAuth2 client can’t use a secret to prove its identity. Originally, the OAuth2 ‘implicit grant flow’ was created for this situation, as it skipped this authentication step. However, this method had security weaknesses and was officially removed in OAuth standard version 2.1.
It’s been replaced by the authorisation grant flow with PKCE (Proof Key for Code Exchange). PKCE is clever because it uses a unique, temporary challenge for each login attempt instead of a fixed, reusable secret. By using this flow, the SPA doesn’t need to store a secret value, but can still prove its identity securely.
The second problem SPAs face is how to store the access tokens (and optional refresh tokens). These tokens need to be stored somewhere in the browser, like localStorage, sessionStorage or in memory. While each storage type has its pros and cons, they are all at risk from malicious JavaScript. With modern SPAs being so complex, it’s very difficult to completely protect against Cross-Site Scripting (XSS) attacks, making token theft an attractive target for attackers. While there isn’t a universally agreed-upon solution for this, we’ll explain a popular design pattern that improves token security in SPAs.
The Backend for Frontend pattern
The Backend for Frontend (BFF) is a design pattern where each frontend application (like an iOS app, Android app, or web app) gets its own dedicated backend. This is different from having one giant backend that serves everything. In terms of token security, the BFF is a small, simple backend that works alongside the SPA.
Here’s how it works:
- The BFF handles all the OAuth2 interactions with the Authorisation Server. Because the BFF runs on a secure server you control, it’s a ‘confidential client’ and can safely store secrets.
- The OAuth2 access and refresh tokens are stored securely in the BFF.
- The BFF creates a secure, cookie-based session with the frontend SPA.
- Every API request from the SPA goes through the BFF. The BFF checks the session cookie, adds the correct access token to the request, and then sends it to the main API.
An SPA using a BFF for its OAuth2 security would look something like this:

Considerations and security pitfalls
The BFF pattern uses a session cookie to find the user’s tokens. Sessions can be managed on the server or the client. Server-side sessions store only a reference ID in the cookie, while the actual session data lives on the backend. This gives you full control, but to keep the service running smoothly, this session information needs to be shared across several servers.
Client-side sessions put all the session data inside the browser cookie itself. To stop anyone tampering with it, the cookie must be digitally signed and, optionally, encrypted. Client-side cookies mean you don’t need to synchronise session data, but they can make it harder to revoke a user’s session. However, with a BFF, session revocation isn’t a big concern, as the tokens themselves are controlled by the backend anyway. You just need to revoke the user’s access token on the server, without needing to invalidate the cookie. For this reason, client-based sessions are usually the best choice for a BFF architecture.
You should always follow standard cookie security rules. The session cookie should be flagged as Secure, HttpOnly, and SameSite=strict. You shouldn’t set a Domain attribute, which locks the cookie to a specific hostname. To enforce these rules in the browser, you should also prefix the cookie’s name with __Host-.
Conclusion
Single-page applications (SPAs) are very popular, but they create security challenges, especially with OAuth2 authorisation. Storing tokens in the browser’s sessionStorage or localStorage is risky because they’re vulnerable to JavaScript injection attacks.
To solve this, the Backend for Frontend (BFF) pattern is a great solution. In this model, each frontend has its own backend that handles all the OAuth2 interactions. It stores access and refresh tokens securely on the server. The BFF establishes a cookie-based session with the frontend and acts as a trusted proxy for all API requests, adding the necessary access token before sending them on.
Secure AI, Sustainable Value: Your CISO’s Guide to AI Risk Management

Get your free Whitepaper if you want to:
- Learn to identify and manage unique AI security challenges
- Implement Devoteam’s AI Cyber Trust Cube – our framework for trusted and secure AI deployments
- Align AI with your organisation’s sustainability goals
- Gain insights from Devoteam’s leading AI security experts.
