TWD Auth0
January 5, 2026 ยท View on GitHub
Test While Developing (TWD): An in-browser testing approach that validates full user workflows in real time. Combined with a secure BFF (Backend For Frontend) auth pattern, this project demonstrates production-grade authentication and testing practices.
๐ Architecture
Backend (BFF)
backend-service/
โโโ routes/
โ โโโ auth.ts # OAuth2 login/callback/logout
โ โโโ notes.ts # Protected API (requires session)
โโโ db/
โ โโโ schema.ts # Users + Notes tables with relations
โ โโโ client.ts # Drizzle + LibSQL
โโโ session.ts # HttpOnly cookie config
โโโ tests/
โโโ auth.test.ts # Full OAuth flow validation
โโโ notes.test.ts # Protected API + user isolation
Key insight: The session cookie is HttpOnly and SameSite=Lax, so the frontend never sees tokens. The loader just calls /api/me to check if authenticated.
Frontend (React Router v7)
src/
โโโ pages/
โ โโโ App/
โ โ โโโ loader.ts # Fetches session + notes (redirects if 401)
โ โ โโโ actions.ts # Form submission (create note via useFetcher)
โ โ โโโ App.tsx # Authenticated user home
โ โโโ Login/
โ โโโ loader.ts # Redirects auth users back to /
โโโ api/
โ โโโ client.ts # Axios instance with credentials
โ โโโ auth.ts # getSession() helper
โ โโโ notes.ts # fetchNotes(), createNote() helpers
โโโ components/
โ โโโ Notes.tsx # useFetcher form for notes
โโโ twd-test/
โโโ app.twd.test.ts # Full user journey (profile + notes)
โโโ login.twd.test.ts # Login redirect flow
โโโ authUtils.ts # Mock auth state
โจ Testing Philosophy: TWD (Test While Developing)
TWD is a radical new approach to testing web apps. Instead of running tests in Node.js with JSDOM or spinning up full E2E suites, TWD runs tests directly in the browser alongside your app.
- Real browser environment: No JSDOM quirks, no synthetic Node.js environment. Tests run where the app actually runs.
- Request mocking without complexity:
twd.mockRequest()instead of MSW handlers. - Testing Library built-in:
screenDom.getByRole()for semantic queries. - Instant feedback: Refresh = tests run. No test bundling, no startup overhead.
Example TWD Test
import { twd, userEvent, screenDom } from "twd-js";
import { describe, it, beforeEach } from "twd-js/runner";
import { mockAuthenticatedUser } from "./authUtils";
describe("Notes App", () => {
beforeEach(() => {
twd.clearRequestMockRules();
mockAuthenticatedUser({ id: "1", name: "John", email: "john@test.com" });
});
it("should create and display a new note", async () => {
// Mock the API response BEFORE the action
twd.mockRequest("createNote", {
method: "POST",
url: "/api/notes",
response: { id: 1, title: "Test", content: "My note", createdAt: Date.now() },
});
// Fill the form using Testing Library semantics
const titleInput = screenDom.getByLabelText("Title");
const submitBtn = screenDom.getByRole("button", { name: "Add note" });
await userEvent.type(titleInput, "Test");
await userEvent.click(submitBtn);
// Wait for the mocked request
await twd.waitForRequest("createNote");
// Assert the note appears in the DOM
const note = screenDom.getByText("Test");
note.should("be.visible");
});
});
What's being tested: React Router action โ useFetcher submission โ API call โ loader revalidation โ DOM update. All real, all in the browser.
๐ Auth Flow
1. Unauthenticated User Visits /
GET / (no session cookie)
โ
loaderApp checks /api/me โ 401
โ
Redirect to /login
2. User Clicks "Log In"
GET /auth/login
โ
Redirect to Auth0 (with client_id, redirect_uri, state)
3. Auth0 Redirects Back
GET /auth/callback?code=xxx&state=yyy
โ
BFF exchanges code for tokens (server-side only)
โ
BFF creates session, sets HttpOnly cookie
โ
Redirect to / (with session cookie)
4. Home Page Loads
GET / (with session cookie)
โ
loaderApp calls /api/me โ 200 + user data
โ
loaderApp calls /api/notes โ 200 + user's notes
โ
Page renders with profile + notes
5. User Creates a Note
POST / (useFetcher form)
โ
actionApp receives FormData, calls POST /api/notes
โ
BFF checks session, validates user_id, inserts note
โ
actionApp returns note, router revalidates loaderApp
โ
DOM updates with new note
๐ Quick Start
Backend
cd backend-service
npm install
npm run db:push # Create SQLite tables
npm run dev # Starts on :3000
Set up .env:
AUTH0_DOMAIN=your-tenant.auth0.com
AUTH0_CLIENT_ID=xxxx
AUTH0_CLIENT_SECRET=xxxx
AUTH0_REDIRECT_URI=http://localhost:5173/auth/callback
Frontend
npm install
npm run dev # Starts on :5173 (proxies /auth and /api to :3000)
Visit http://localhost:5173 and click "Log In" to start the OAuth flow.
Run Tests
In the browser (http://localhost:5173):
- Open DevTools console
- TWD tests run in the sidebar; watch them pass in real time.
๐งช Backend Tests (Node.js)
cd backend-service
npm test # Runs Vitest with real SQLite
Test highlights:
auth.test.ts: Full OAuth flow (login redirect โ callback โ token exchange โ session โ logout).notes.test.ts: Protected API (verify user isolation, CRUD).
๐ Learning Goals
By exploring this project, you'll understand:
- OAuth2 Security: Why tokens stay server-side, how HttpOnly cookies work.
- React Router Data APIs: Loaders for data-before-render, actions for mutations, error boundaries.
- BFF Pattern: Why a backend layer protects your frontend from auth complexity.
- Testing Workflows: How TWD tests validate full user journeys faster than traditional E2E.
- Type Safety: Using TypeScript + Axios helpers to catch API bugs at compile time.
๐ Key Files to Read
- backend-service/routes/auth.ts โ Full OAuth implementation with session management.
- backend-service/routes/notes.ts โ User-scoped API with session checks.
- src/pages/App/loader.ts โ Auth guard + data loader pattern.
- src/pages/App/actions.ts โ Form submission via React Router actions.
- src/twd-test/login.twd.test.ts โ Login workflow validation.
- src/twd-test/app.twd.test.ts โ Notes app workflow validation.
๐ Resources
- Auth0 Docs
- React Router v7 Loaders/Actions
- Drizzle ORM
- TWD (Test While Developing) โ The custom test runner powering this project