BFF – FAQ
General
- What is the BFF? A backend that terminates OAuth, issues a session cookie, enforces authorization via a PDP, and proxies to internal services. See: BFF for SPAs overview.
- Where are APIs defined?
ServiceConfigs/BFF/config/routes.yaml(canonical/api/...paths → upstream services,auth: session). - Where are authorization rules mapped?
ServiceConfigs/BFF/config/pdp.yamlunderendpoint_map(path/method → resource/action/id_from/props).
What is a BFF (and how ours differs from API gateways)?
- Definition: A Backend‑for‑Frontend is an app‑specific backend that owns auth flows (PKCE/PAR, sessions/CSRF), composes data from multiple services, enforces authorization via PDP, and exposes a stable, UX‑oriented API to the frontend.
- Our BFF (this repo):
- Auth: full OAuth login, session cookies, CSRF, optional DPoP/mTLS; ForwardAuth integration at edge; no tokens in the browser for same‑origin SPAs.
- Authorization: calls a PDP (AuthZEN) using
pdp.yaml:endpoint_map; caches decisions with separate allow/deny TTLs. - Composition: aggregates/orchestrates calls, handles streaming, uploads, background work, and error shaping.
- Contracts: canonical
/api/<app>/**viaroutes.yaml; custom endpoints where composition/security is required.
- vs API gateways (Kong/NGINX/Traefik):
- Gateways excel at L7 routing, rate limiting, TLS, and header transforms. They don’t own app auth flows, sessions/CSRF, or PDP enforcement per endpoint.
- In our stack, Traefik provides edge routing, TLS, security headers, and ForwardAuth. The BFF owns sessions, PDP checks, and business composition. Kong would overlap with Traefik in routing/middleware but still wouldn’t replace the BFF’s app logic.
Admins
- Where is configuration kept?
ServiceConfigs/BFF/config/*.yamlincludingroutes.yaml,pdp.yaml,idps.yaml,logging.yaml, and more. - How do I add a new API surface? Add a service in
routes.yaml:services, then a route entry underrouteswith your/api/<app>/*path,target_service,upstream_path, methods, andauth: session.
DevOps
- How is it run locally?
CRUDService/docker-compose-authzen4.yml(stack with Traefik, BFF, Redis, PDP, IdP). Health checks:http://localhost:8000/health(BFF),http://localhost:8080/ping(Traefik). - How does Traefik authenticate requests? ForwardAuth hits BFF
/auth/forward(verified by tests in TEST_EXECUTION_GUIDE). BFF validates session, then routes perroutes.yaml. - Which PDP endpoints are exposed via BFF? See
routes.yamlentries like/access/v1/evaluation(preserve path) topdp_service.
Frontend (SPA)
- How do SPAs integrate? Set
VITE_BFF_BASE_URL, wrap withAuthProviderfrom@empowernow/bff-auth-react, and call APIs viaapiClient/fetchWithAuth(cookies are sent automatically). Code verified inpdp_ui/frontendandidp_ui/frontend. - Do I send Authorization headers? No for same‑origin; the BFF uses httpOnly cookies. See: Integrate a React SPA with the BFF and SPA Golden Path.
Backend Developers
-
How are permissions checked?
core/permissions.pybuilds context (roles, headers, query, body subset, correlation ID),services/path_mapper.pymaps request to resource/action frompdp.yaml:endpoint_map, thenservices/pdp_client.pycalls PDP and caches decisions. -
Where are PDP endpoints configured?
pdp.yaml:endpoints(e.g.,evaluation: "v1/evaluation"). The client uses these for internal PDP calls. -
When do I need a custom BFF endpoint instead of just
routes.yaml?- Use
routes.yamlwhen:- You are proxying a single upstream with optional path templating (
upstream_pathwith{path}), preserving the path, selecting methods, and applying built‑in auth modes (auth: session | bearer | none) andstreaming: truefor SSE.
- You are proxying a single upstream with optional path templating (
- Create a custom BFF endpoint when you need any of the following (not expressible in
routes.yaml):- Aggregation/orchestration: one client call fan‑outs to multiple services, merges results, or sequences calls transactionally.
- Security transformations: token exchange, signing (DPoP, mTLS client assertions), presigned URL minting, step‑up auth, or minting/downscoping
Authorizationheaders beyond pass‑through. - Request/response shaping: canonical validation, schema mapping, pagination unification, partial field selection, error normalization, or PII redaction.
- Stateful flows: CSRF‑bound actions with server state, idempotency keys, retries/circuit breakers, or saga choreography.
- Long‑running or background work: enqueue a job and return 202 + status polling endpoint.
- Specialized streaming: upload/download mediation (multipart, chunking, encryption/AV scanning) or WebSockets.
- Per‑user/business rate limits or caching that can’t be handled by Traefik’s generic middleware.
- Concrete examples in this repo:
- Metrics sink handled directly by BFF:
POST /api/metrics(see comment inServiceConfigs/BFF/config/routes.yaml: “Metrics sink is handled directly by BFF code at /api/metrics (POST). No YAML proxy entry needed.”) - Auth router endpoints:
/auth/*(login, callback, verify/forward, csrf, token) are implemented in the BFF, not proxied viaroutes.yaml. - Some SPA streaming endpoints are terminated by the BFF first (see Traefik labels in
CRUDService/docker-compose-authzen4.ymlforbff-*-streaming).
- Metrics sink handled directly by BFF:
- Quick checklist:
- Does the route require calling more than one upstream? → Custom endpoint.
- Do you need to alter auth materials (mint/transform tokens or headers)? → Custom endpoint.
- Do you need to validate or reshape request/response bodies beyond simple path rewrites? → Custom endpoint.
- Is it WebSocket, presigned upload/download, or background job control? → Custom endpoint.
- Otherwise, if it’s a straight proxy with optional SSE, prefer
routes.yaml.
- Use
Security & Auditors
- What authorizes access? AuthZEN PDP evaluation using mapped resource/action and context. Deny or allow decisions may be cached with different TTLs (
pdp.yaml:cache.ttl_allow/ttl_deny). - Where is direct PDP exposure controlled? Externally via BFF
routes.yamlentries under PDP Service Routes (e.g.,/access/v1/evaluation), internally viapdp_client(v1/evaluation).
QA & Testing
- How do we prove it works? Follow the QA Test Execution how‑to. Critical tests verify: Traefik ForwardAuth → BFF chain, middleware/routing, and real user workflows across IdP UI, Visual Designer, and PDP UI as documented in TEST_EXECUTION_GUIDE.
Troubleshooting quick answers
- 401 vs 403? 401 = unauthenticated (login). 403 = authenticated but PDP denied.
- “/api/api/...” double prefix? Use the app wrappers which strip leading
/apibefore callingapiClient. - DNS errors with
*.ocg.labs.empowernow.ai? Add hosts file entries pointing to 127.0.0.1 for local.
Pointers
- Overview: BFF for React SPAs — How It Works
- Tutorial: React SPA + BFF — Golden Path
- How‑to: Integrate a React SPA with the BFF
- How‑to: Configure PDP (pdp.yaml)
- Reference: QA — Troubleshooting Checklist