Skip to content

Backend-Mandatory Auth + Sync Local Flow ​

Date: 2026-04-15
Scope: exact implementation flow for backend-authenticated frontend sessions, refresh rotation, sync replay, and local testing.

1) Exact implementation flow ​

1.1 Login (frontend → backend) ​

  1. app/src/app/pages/LoginPage.tsx calls AuthContext.login(identifier, password).
  2. If VITE_BACKEND_URL is set, frontend uses backend auth mode (app/src/modules/auth/backendAuth.ts).
  3. Frontend sends POST /api/v1/auth/login with { email, password }.
    • If the user typed admin, chamador, relatorios, or cadastro, frontend normalizes to:
      • admin@neemias.local
      • chamador@neemias.local
      • relatorios@neemias.local
      • cadastro@neemias.local
  4. Backend verifies password (workers/src/modules/auth/password.ts) and creates auth session (workers/src/routes/auth.ts):
    • creates refresh token
    • stores hashed refresh token in auth_refresh_sessions
    • creates CSRF token
    • signs short-lived access token
  5. Backend returns:
    • accessToken
    • accessTokenExpiresAt
    • refreshToken (bearer mode) or httpOnly cookie (cookie mode)
    • csrfToken
    • user payload
  6. Frontend persists session metadata in IndexedDB sessions and user metadata in users (AuthContext.persistBackendSession()), then loads students from backend (fetchStudentsFromBackend).

1.2 Refresh-token rotation ​

  1. Frontend calls POST /api/v1/auth/refresh when needed (hydration/retry path).
  2. Backend validates refresh token hash in auth_refresh_sessions.
  3. Backend creates a new refresh/access pair and revokes old refresh session:
    • sets revoked_at, rotated_at, replaced_by
  4. Frontend replaces local session metadata with the new session artifacts.

1.3 Sync replay and auth bridge ​

  1. Offline queue drain (OfflineContext) calls syncQueueEntryWithBackend() for each pending item.
  2. Each request sends:
    • Authorization: Bearer <accessToken>
    • X-Device-Id
    • Idempotency-Key
    • X-CSRF-Token when available
  3. If backend returns 401:
    • frontend attempts refresh (AuthContext.refreshAccessToken())
    • if refresh fails, session is marked EXPIRED
    • queue entries remain pending/retrying (not force-synced)
  4. Conflict metadata from backend conflicts[] is written to local attendance events and surfaced in UI.

When backend is configured with AUTH_SESSION_MODE=cookie:

  • refresh token is stored in httpOnly cookie
  • mutating routes enforce CSRF via X-CSRF-Token
  • frontend includes credentials (credentials: "include") for auth/sync requests

2) Local setup (backend mandatory) ​

2.1 Backend Worker (terminal 1) ​

The backend is a Cloudflare Worker backed by D1 (SQLite). Local development uses wrangler dev in local mode — no PostgreSQL or Docker needed.

bash
cd /home/runner/work/neemias/neemias
pnpm install

Apply D1 migrations to the local database:

bash
pnpm db:migrate:local

Seed demo users and data (idempotent — returns 409 ALREADY_SEEDED if already seeded):

bash
pnpm db:seed

Run the Worker locally with wrangler dev --local (local SQLite D1; AUTH_MODE comes from workers/.dev.vars):

bash
pnpm dev:worker
# equivalent direct command:
cd workers && npx wrangler dev --local --port 8788

2.2 Frontend (terminal 2) ​

Create app env:

bash
cd /home/runner/work/neemias/neemias/app
cp .env.example .env

Run frontend:

bash
cd /home/runner/work/neemias/neemias
pnpm --dir app dev

2.3 Demo login credentials (backend seed) ​

  • admin / senha123
  • chamador / senha123
  • relatorios / senha123
  • cadastro / senha123

Equivalent backend emails:

  • admin@neemias.local
  • chamador@neemias.local
  • relatorios@neemias.local
  • cadastro@neemias.local

2.4 Connectivity checks (frontend must see backend) ​

  1. Backend health:
bash
curl http://localhost:8788/api/v1/health
  1. Browser DevTools in frontend:
    • login request should target http://localhost:8788/api/v1/auth/login
    • sync request should target http://localhost:8788/api/v1/sync/events
  2. If requests are missing:
    • verify app/.env has VITE_BACKEND_URL=http://localhost:8788
    • restart frontend dev server after editing .env

3) Known boundary ​

PII encryption-at-rest lifecycle is now implemented for session secrets and sensitive IndexedDB payload fields using browser-native crypto envelopes, in-memory key clear on logout/expiry, and re-auth-triggered key rotation.

Distribuído sob licença MIT.