ADR 0003: Use Auth0 BFF sessions and approved OAuth clients
This record defines customer, operator, and external-agent authentication.Context
The customer browser must not store identity or Perflo bearer tokens. Autonomous agents need revocable offline access tied to customer mandates.Decision
Use an Auth0 confidential application for the same-origin backend-for-frontend (BFF). Store session state in Redis and set an opaque HTTP-only cookie. Require cross-site request forgery protection and transaction-bound step-up for sensitive actions. Use a separate Auth0 operator application with mandatory multifactor authentication. Register external clients manually and use authorization code with Proof Key for Code Exchange (PKCE), rotating refresh tokens, and short-lived API tokens. Sensitive customer actions use server-issued confirmation intents. Each intent is bound to the customer, action, and canonical payload hash, expires after ten minutes, and can be consumed once. The Auth0 step-up callback confirms the intent only after matching the customer subject and multifactor claim. A recent multifactor session may confirm a new intent without another redirect, but it cannot authorize a different payload. The customer login cannot accept an operator role. Operator sessions must originate from the dedicated operator client and carry the operator role; this prevents role leakage in the customer application from opening the restricted console.Consequences
OAuth scopes permit access to an API family, while the mandate binds a client and delegated customer subject to a customer, recipient, and limits. Operations and audit events retain both the subject and OAuth client ID so a different client cannot read the result and operators can attribute each delegated action. Browser compromise cannot directly read server-held tokens.Rejected alternatives
- Clerk: its standard session token must remain browser-readable.
- Independent Privy: it duplicates Perflo’s identity and wallet control plane.
- Cloudflare Access one-time password: it does not cover retail identity lifecycle and transaction authorization.