Next.js middleware for LMS auth & tenancy
Problem¶
No middleware.ts exists in either app. The LMS resolves tenants in Auth.js callbacks and checks auth in individual route handlers. Consequences:
- Cost: Unauthenticated requests to protected routes still invoke the Node.js runtime (billed per invocation on Vercel)
- Duplication: Tenant resolution logic repeated in auth callbacks and RBAC middleware
- UX: No centralized redirect for expired sessions — each page errors independently
Proposal¶
Add apps/lms/middleware.ts with:
- Auth check: Redirect to
/learn/sign-infor protected routes when no session token cookie exists - Tenant header injection: Resolve tenant slug from hostname once, pass as
x-tenant-slugheader to downstream - Static asset bypass: Matcher excludes
/_next/*,/api/auth/*,/api/health,/favicon/*
Important constraints:
- Middleware runs on Vercel Edge — cannot do DB lookups
- RBAC stays in route handlers (requires DB for permission checks)
- Auth.js session validation remains in callbacks (middleware only checks cookie presence)
Acceptance criteria¶
-
middleware.tscreated withconfig.matcherexcluding static paths - Unauthenticated requests to
/learn/*and/admin/*redirect to sign-in -
x-tenant-slugheader set from hostname parsing -
/api/health,/api/auth/*,/_next/*bypass middleware - Existing auth flow unaffected (middleware is additive, not replacement)
-
npm run checkpasses - E2E auth tests still pass
Out of scope¶
- Edge-level rate limiting (T-014 — requires Upstash Redis at edge)
- CMS middleware (single-tenant, less benefit)
- Geo-routing or A/B testing
Notes / decisions log¶
- 2026-07-07: Proposed. Medium effort due to need for careful matcher config and testing auth edge cases (token refresh, OAuth callback).
- 2026-07-09: Deferred — moved to tickets/deferred/; no active implementation planned.