SPA Auth Flows with the BFF
Right mental model
- The SPA delegates OAuth/OIDC to the BFF. The BFF extracts identity from
id_token.suband creates a session; the SPA only uses the session cookie. - Backend service tokens used by the BFF (client-credential or token-exchange) are never exposed to the browser and are not the user identity.
Verified behavior in current SPAs
- Auth provider: apps wrap
<App />withAuthProviderfrom@empowernow/bff-auth-reactand callsetBaseUrl(VITE_BFF_BASE_URL || '/api'). - Guarding: both SPAs use an
AuthGuardthat reads{ isAuthenticated, isLoading }fromuseAuth()and allows public routes['/login', '/callback', '/auth-debug']. - Base URL: both SPAs default to
/apiwhen co-hosted with the BFF; otherwise setVITE_BFF_BASE_URL.
Login flow (observed)
- The guard redirects unauthenticated users to
/login?returnUrl=.... - Each frontend includes a
Loginpage undercomponents/Loginthat initiates auth via the BFF/IdP. - The guard treats
/callbackas public; callback handling is present (e.g.,idp_ui/src/components/AuthCallback/index.tsx).
Logout flow
- Use your app’s login page or top‑nav to surface a logout action. The
@empowernow/bff-auth-reactprovider is expected to expose logout; the exact method name is not in this repo. If unavailable, implement a call to the BFF’s auth router logout endpoint (served by BFF, not viaroutes.yaml).
Sequence (high level)
Public routes vs guards (verified)
- Public:
/login,/callback,/auth-debug - Guard everything else using
AuthGuard.
Reading current auth state
- Use
const { isAuthenticated, isLoading } = useAuth()from@empowernow/bff-auth-react. - This repo does not include a user profile hook/shape; surface minimal UI based on
isAuthenticatedand call backend APIs for user-specific data as needed.