BFF for React SPAs — How It Works
The right mental model
- The SPA never handles OAuth tokens. The BFF terminates OAuth/OIDC, derives the user identity from
id_token.sub, creates a secure session cookie, and proxies/api/...requests using server-held service tokens. - Service tokens (client-credential or token-exchange) identify the BFF as a client to backends; they are not the user identity and are never exposed to the browser.
Who this is for
- React SPA developers new to the Backend‑for‑Frontend (BFF) model.
What the BFF does
- Terminates OAuth in the backend; the browser never sees access tokens
- Issues a secure session cookie; SPAs call the BFF at
/api/... - Enforces authZ per request via PDP (AuthZEN) using
pdp.yaml+ path mapping - Proxies requests to backend services defined in
routes.yaml
End‑to‑end flow
How SPA-local paths route
- Think of
/apias the BFF’s front door. The SPA never talks directly to backend services. - Traefik routes
/api/**to the BFF. The BFF readsroutes.yamland translates the client path to a backend path.
Example translation
GET /api/crud/forms/123 → BFF → GET http://crud_service/forms/123
In dev, VITE_BFF_BASE_URL can be an absolute BFF origin; in prod, it’s usually same‑origin /api.
Automation Studio (Visual Designer) specifics
- Front end for CRUDService.
- SPA calls:
/api/crud/...(CRUD + SSE)/access/v1/evaluationand/access/v1/evaluations(PDP, preserved path topdp_service)
- Traefik forwards to the BFF; BFF proxies per
routes.yaml. - Include cookies: fetch
credentials: 'include', axioswithCredentials: true.
See also
- Reference →
SPA PDP usagefor which SPAs call the PDP, where, and with what payloads.
Where things are configured
- App API surface:
ServiceConfigs/BFF/config/routes.yaml - PDP mapping + performance:
ServiceConfigs/BFF/config/pdp.yaml - SPA wiring:
src/main.tsxusesAuthProviderandsetBaseUrlfrom@empowernow/bff-auth-react
Key properties for SPAs
- No Authorization header needed for same‑origin calls; auth is cookie‑based
- Use canonical
/api/...paths; BFF routes to services and checks permissions - 401 = not logged in; 403 = PDP denied