compassmock/docs/AUTH-IMPLEMENTATION.md
Nicholai 2f613ef453
feat(auth): add WorkOS authentication system (#27)
* feat(schema): add auth, people, and financial tables

Add users, organizations, teams, groups, and project
members tables. Extend customers/vendors with netsuite
fields. Add netsuite schema for invoices, bills,
payments, and credit memos. Include all migrations,
seeds, new UI primitives, and config updates.

* feat(auth): add WorkOS authentication system

Add login, signup, password reset, email verification,
and invitation flows via WorkOS AuthKit. Includes auth
middleware, permission helpers, dev mode fallbacks,
and auth page components.

* ci: retrigger build

---------

Co-authored-by: Nicholai <nicholaivogelfilms@gmail.com>
2026-02-04 16:24:25 -07:00

6.6 KiB
Executable File

Authentication System Implementation

Overview

Custom authentication system integrated with WorkOS API, replacing hosted UI with mobile-first custom pages that match Compass design language.

Implemented Features

Phase 1: Foundation

  • WorkOS client wrapper (src/lib/workos-client.ts)
  • Auth layout with centered card (src/app/(auth)/layout.tsx)
  • Reusable password input with visibility toggle (src/components/auth/password-input.tsx)

Phase 2: Login Flow

  • Login API endpoint (src/app/api/auth/login/route.ts)
  • Password login form (src/components/auth/login-form.tsx)
  • Passwordless login form with 6-digit codes (src/components/auth/passwordless-form.tsx)
  • Login page with tabs (src/app/(auth)/login/page.tsx)

Phase 3: Signup & Verification

  • Signup API endpoint (src/app/api/auth/signup/route.ts)
  • Email verification API endpoint (src/app/api/auth/verify-email/route.ts)
  • Signup form with validation (src/components/auth/signup-form.tsx)
  • Email verification form (src/components/auth/verify-email-form.tsx)
  • Signup page (src/app/(auth)/signup/page.tsx)
  • Verification page (src/app/(auth)/verify-email/page.tsx)

Phase 4: Password Reset

  • Password reset request API (src/app/api/auth/password-reset/route.ts)
  • Password reset confirmation API (src/app/api/auth/reset-password/route.ts)
  • Reset request form (src/components/auth/reset-password-form.tsx)
  • Set new password form (src/components/auth/set-password-form.tsx)
  • Reset password pages (src/app/(auth)/reset-password/)

Phase 5: Invite Acceptance

  • Invite acceptance API (src/app/api/auth/accept-invite/route.ts)
  • Invite form (src/components/auth/invite-form.tsx)
  • Invite page (src/app/(auth)/invite/[token]/page.tsx)

Phase 6: Middleware & Polish

  • Route protection middleware (src/middleware.ts)
  • Security headers (X-Frame-Options, X-Content-Type-Options, HSTS)
  • Helper functions in src/lib/auth.ts (requireAuth, requireEmailVerified)
  • OAuth callback route (src/app/api/auth/callback/route.ts)
  • Updated wrangler.jsonc with WORKOS_REDIRECT_URI

Dev Mode Functionality

All authentication flows work in development mode without WorkOS credentials:

  • Login redirects to dashboard immediately
  • Signup creates mock users
  • Protected routes are accessible
  • All forms validate correctly

Production Deployment Checklist

1. WorkOS Configuration

Set these secrets via wrangler secret put:

wrangler secret put WORKOS_API_KEY
# Enter: sk_live_...

wrangler secret put WORKOS_CLIENT_ID
# Enter: client_...

wrangler secret put WORKOS_COOKIE_PASSWORD
# Enter: [32+ character random string]

Generate cookie password:

node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

2. Environment Variables

Already configured in wrangler.jsonc:

  • WORKOS_REDIRECT_URI: https://compass.openrangeconstruction.ltd/api/auth/callback

3. WorkOS Dashboard Setup

  1. Go to https://dashboard.workos.com
  2. Create a new organization (or use existing)
  3. Configure redirect URI: https://compass.openrangeconstruction.ltd/api/auth/callback
  4. Enable authentication methods:
    • Email/Password
    • Magic Auth (passwordless codes)
  5. Copy Client ID and API Key

4. Cloudflare Rate Limiting

Configure rate limiting rules in Cloudflare dashboard:

  • /api/auth/login: 5 attempts per 15 minutes per IP
  • /api/auth/signup: 3 attempts per hour per IP
  • /api/auth/password-reset: 3 attempts per hour per IP

5. Test Production Auth Flow

  1. Deploy to production: bun run deploy
  2. Navigate to login page
  3. Test password login
  4. Test passwordless login
  5. Test signup flow
  6. Test email verification
  7. Test password reset
  8. Verify protected routes redirect to login

6. Invite Users

Use existing People page to invite users:

  1. Go to /dashboard/people
  2. Click "Invite User"
  3. User receives WorkOS invitation email
  4. User accepts via /invite/[token] page

Security Features

  • HTTPS-only (enforced via Cloudflare)
  • CSRF protection (Next.js built-in + WorkOS)
  • Rate limiting (via Cloudflare rules - needs setup)
  • Password strength validation (8+ chars, uppercase, lowercase, number)
  • Code expiration (10 minutes for magic auth)
  • Session rotation (WorkOS handles refresh tokens)
  • Secure headers (X-Frame-Options, HSTS, nosniff)
  • Email verification enforcement (via middleware)
  • Cookie encryption (AES-GCM via WORKOS_COOKIE_PASSWORD)

Mobile Optimizations

  • 44px touch targets for primary actions
  • 16px input text (prevents iOS zoom)
  • Responsive layouts (flex-col sm:flex-row)
  • Proper keyboard types (email, password, numeric)
  • Auto-submit on 6-digit code completion
  • Full-width buttons on mobile

Known Issues

None currently. All lint errors have been fixed.

Next Steps (Future Enhancements)

  1. Add 2FA/MFA support (WorkOS supports this)
  2. Add OAuth providers (Google, Microsoft) for SSO
  3. Add audit logging for sensitive auth events
  4. Implement session timeout warnings
  5. Add "remember me" functionality
  6. Add account lockout after failed attempts
  7. Add "Login with passkey" support

Files Created

Core Infrastructure

  • src/lib/workos-client.ts
  • src/app/(auth)/layout.tsx
  • src/components/auth/password-input.tsx

Login

  • src/app/api/auth/login/route.ts
  • src/components/auth/login-form.tsx
  • src/components/auth/passwordless-form.tsx
  • src/app/(auth)/login/page.tsx

Signup & Verification

  • src/app/api/auth/signup/route.ts
  • src/app/api/auth/verify-email/route.ts
  • src/components/auth/signup-form.tsx
  • src/components/auth/verify-email-form.tsx
  • src/app/(auth)/signup/page.tsx
  • src/app/(auth)/verify-email/page.tsx

Password Reset

  • src/app/api/auth/password-reset/route.ts
  • src/app/api/auth/reset-password/route.ts
  • src/components/auth/reset-password-form.tsx
  • src/components/auth/set-password-form.tsx
  • src/app/(auth)/reset-password/page.tsx
  • src/app/(auth)/reset-password/[token]/page.tsx

Invites

  • src/app/api/auth/accept-invite/route.ts
  • src/components/auth/invite-form.tsx
  • src/app/(auth)/invite/[token]/page.tsx

OAuth

  • src/app/api/auth/callback/route.ts

Files Modified

  • src/lib/auth.ts - Added requireAuth() and requireEmailVerified()
  • src/middleware.ts - Added route protection and security headers
  • wrangler.jsonc - Added WORKOS_REDIRECT_URI variable

Testing in Dev Mode

All authentication pages are accessible at:

Dev server running on port 3004 (3000 was in use).