Skip to Content
Core ConceptsBackend for Frontend (BFF)

Backend for Frontend (BFF)

A Backend for Frontend, or BFF, protects a browser app by keeping OAuth tokens away from browser JavaScript.

With an AuthGate BFF gateway, users open your app through the gateway URL:

https://your-store.authgate.site

AuthGate can serve your registered frontend app, handle login under /bff/*, and forward API calls to your backend services.

Why BFF exists

Many beginner apps store access tokens in localStorage. That is easy, but risky.

If harmful JavaScript runs on the page, it can read localStorage. If the access token is there, the attacker can copy it.

A BFF avoids that pattern:

  • the browser does not receive the access token
  • AuthGate stores the BFF session server-side
  • the browser only receives an HttpOnly cookie
  • JavaScript cannot read an HttpOnly cookie

Frontend app

In a BFF gateway, the frontend app is the deployed browser app that AuthGate should serve.

Example:

ThingExample
Frontend app originhttps://mori-market.vercel.app
Gateway entrypointhttps://mori-market.authgate.site

Users should open the gateway entrypoint, not the original frontend origin.

That keeps pages, session endpoints, and API routes on the same site.

BFF session endpoints

AuthGate reserves these paths for the BFF flow:

EndpointMeaning
GET /bff/loginStarts OAuth2 login with the IAM client bound to the gateway.
GET /bff/callbackReceives the OAuth2 authorization code and creates the BFF session.
GET /bff/meChecks whether the browser has a valid BFF session.
POST /bff/logoutDeletes the BFF session and clears the cookie.

Your frontend can check the session like this:

const response = await fetch('/bff/me', { credentials: 'include' })

HttpOnly session

After login, AuthGate creates a cookie named:

AUTHGATE_BFF_SESSION

Important details:

  • it is HttpOnly, so frontend JavaScript cannot read it
  • it uses SameSite=Lax
  • secure routes validate this session before forwarding the request
  • AuthGate strips the BFF session cookie before forwarding to your upstream service

Do not write browser code that tries to read the BFF cookie. That is the point of HttpOnly: the browser sends it automatically, but JavaScript cannot access it.

Public and secure routes

BFF gateways support both guest and logged-in behavior.

Route typeExampleLogin required?
PUBLICGET /api/productsNo
PUBLICGET /api/products/{id}No
SECUREPOST /api/products/addYes
SECUREPATCH /api/products/{id}Yes

This is useful for normal ecommerce behavior:

  • visitors can view products before login
  • logged-in users can open account pages or perform protected actions

/api/... is not magic. It is a convention that prevents route conflicts.

For example:

PathShould be
/productsfrontend page
/products/1frontend page
/api/productsbackend API route
/api/products/1backend API route

If a gateway route and a frontend page use the same path, the gateway route wins. That can make a page show JSON instead of the real website.

BFF setup checklist

Before testing a BFF app, confirm these five items:

  1. IAM OAuth2 client exists.
  2. BFF gateway is bound to that OAuth2 client.
  3. OAuth2 client contains the gateway callback URL, for example https://your-store.authgate.site/bff/callback.
  4. Frontend app origin is registered in the Frontend Apps tab.
  5. Backend service routes exist for both public reads and secure actions.

What the frontend code should do

For login:

window.location.href = '/bff/login?return_to=/'

For public data:

await fetch('/api/products', { credentials: 'include' })

For secure data:

await fetch('/api/profile', { credentials: 'include' })

The frontend should not store access tokens in localStorage, sessionStorage, or regular readable cookies.

Current gateway behavior

For SECURE BFF routes, AuthGate validates the BFF session at the gateway before forwarding the request to the upstream service.

This means your browser app proves login by sending the BFF session cookie, not by sending an Authorization: Bearer ... header.

Last updated on