If you’ve built or managed a web app, you’ve probably dealt with the headache that is user login and security. You log the user in with OAuth, tokens need to be stored in memory or local state, your code has to rotate expired tokens, and you need to understand how same-site cookies impact silent token refresh, etc., etc.
BFF Authentication offers a way to simplify your auth code while enhancing security, and continuing to provide your end users with a nice login experience. The big change with BFF authentication is that you no longer need to juggle all of this authentication logic on the client - you authenticate the user, store some session state on the server, and use good old browser cookies to handle API authentication. When you have BFF authentication wired up correctly, making an API request from your browser app is as simple as making a fetch:
In this article, we’ll walk through how BFF Authentication works and guide you through the process of building a simple API to implement BFF Authentication in a client application.
- Building web apps with OAuth login flows
- Want to simplify client-side authentication code
- Need secure session-based API authentication
- Moving away from token juggling in the browser
This article does not adhere strictly to the proposed BFF specification. Instead, it aims to illustrate core concepts and essential elements. As the specification evolves and gains broader adoption, certain details may change. BFF is one of several API gateway patterns that can help you manage traffic between frontends and backends.
Want to skip ahead? The complete BFF Authentication example is available on GitHub, or you can deploy it directly using the sample at the bottom of this article.
How BFF Authentication Works
BFF Authentication employs standard OAuth flows to authenticate backend clients. If you’ve worked with OAuth before in frameworks like ExpressJS or ASP.NET, this process should be familiar. The system uses “web app” OAuth flows to authenticate the backend, which then sets a session cookie passed along with each subsequent browser request to the Backend API.
The diagram below shows the steps involved in the initial authentication.
- The Browser App redirects to /auth/login on the Backend API.
- The Backend API constructs an OIDC Authorize URL with the identity provider and redirects to /authorize.
- The user authenticates through available methods (e.g., username/password, passkey, third-party OAuth provider).
- Upon successful authentication, the identity provider redirects back to the Backend API, which then retrieves and validates access_token, id_token, and refresh_token.
- The Backend API fetches the user’s profile information via the /userinfo endpoint.
- User profile, tokens, and session data are stored securely.
- Finally, the Backend API sets a secure session cookie and redirects back to the Browser App.
If you’ve been developing long enough to remember the pre-React and pre-SPA days, BFF Authentication may sound familiar. That’s because it revisits traditional methods involving session cookies and server-side session storage.
OpenID JWT Authentication
Validate JWTs from any OpenID Connect compliant identity provider like Auth0, Okta, or Clerk.
Examining BFF Authentication Code
Before diving into the code snippets, it’s important to note that they have been simplified for readability; error handling and other nuances have been omitted. You can explore the complete project on GitHub for full details.
Initializing OAuth Authentication
The first step initiates the authentication process by sending the user to /auth/login. The backend then constructs an OAuth URL to interface with the identity provider.
Completing the OAuth Cycle
After user authentication, identity provider redirects to the callback which then retrieves tokens and profile information, saves these in a session store, and sets a session cookie.
Client-Side Application Authentication
After the backend authentication the browser will load the client-side app, which now needs to determine two things:
- Whether the user is authenticated.
- The identity of the user.
To acquire this information, the browser app calls the Backend API’s session info endpoint. This endpoint returns the session’s profile information, allowing the client-side app to confirm the login state and display relevant user information.
Following
API security best practices, the
client-side app needs to send the cookie to the Backend API with each request.
By default the browser fetch API won’t
send cookies.
So the credentials property needs to be set to same-origin.
The backend code for the session info is as follows:
BFF vs. Token-in-Browser: Security Comparison
The most common alternative to BFF Authentication is storing tokens directly in
the browser — either in localStorage, sessionStorage, or in-memory. Here’s
how the two approaches compare from a security perspective.
Token-in-Browser stores the access token (and sometimes the refresh token) in client-side JavaScript. This creates several risks:
- XSS vulnerability — Any cross-site scripting attack can read tokens from storage and send them to an attacker. Once stolen, the attacker can make API calls as the user until the token expires.
- Token refresh complexity — The client must handle token expiration, silent renewal, and edge cases like expired refresh tokens. This logic is error-prone and varies across identity providers.
- Third-party cookie restrictions — Modern browsers are increasingly blocking third-party cookies, which breaks silent token refresh flows that rely on hidden iframes.
BFF Authentication avoids these problems by keeping tokens on the server:
- No tokens in the browser — The only credential the browser sees is a session cookie. Even if an XSS attack occurs, the attacker can’t extract an OAuth token.
- HttpOnly cookies — The session cookie is set with the
HttpOnlyflag, which means JavaScript can’t read it. Combined withSameSite=StrictandSecure, the cookie is well-protected against common web attacks. - Server-side refresh — Token renewal happens on the backend, where it’s simpler and more reliable. The client doesn’t need to know about access tokens at all.
The trade-off is that BFF Authentication requires a backend component to manage sessions. If you’re already running a server (or using an API gateway like Zuplo), that’s not a significant cost. If you’re building a purely static SPA with no backend, a BFF adds infrastructure you wouldn’t otherwise need.
When NOT to Use BFF Authentication
BFF Authentication is a strong choice for many web applications, but it’s not the right fit for every scenario. Here are cases where a different approach makes more sense:
- Mobile apps and native clients — Mobile apps typically use OAuth with PKCE and store tokens in the platform’s secure storage (Keychain on iOS, Keystore on Android). These storage mechanisms are sandboxed per app, so the XSS risk that motivates BFF doesn’t apply.
- Machine-to-machine communication — Server-to-server API calls use client credentials grants. There’s no browser involved, so session cookies are irrelevant.
- Static sites with no backend — If your application is entirely client-side (e.g., a static site hosted on a CDN with no server), adding a backend purely for authentication adds complexity. In this case, consider using a hosted authentication service that handles token management for you.
- Short-lived, low-risk applications — For internal tools or prototypes where the security stakes are low, the overhead of setting up BFF Authentication may not be justified. A simpler token-in-browser approach with short-lived tokens could be sufficient.
If your application is a web app with a backend (or an API gateway) and you’re using OAuth to authenticate users, BFF Authentication is almost always the better choice compared to managing tokens in the browser.
Why BFF Authentication Simplifies Your Auth Code
BFF Authentication moves the complexity of OAuth token management from the browser to the server. Instead of juggling access tokens, refresh logic, and silent renewals in client-side code, you authenticate once on the backend and use a session cookie for every subsequent request. The result is simpler frontend code and stronger security — tokens never touch the browser.
If you’re building a web app that uses OAuth and you’re tired of debugging token refresh flows in your SPA, BFF Authentication is worth considering. You get a clean separation between your frontend and your auth logic, and your users still get a smooth login experience.
For a deeper look at how different authentication methods compare, check out our guide on the top API authentication methods.
BFF Authentication Example
A complete Backend for Frontend authentication implementation with OAuth, session management, and secure HTTP-only cookies.