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

200 lines
6.6 KiB
Markdown
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`:
```bash
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:
```bash
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:
- http://localhost:3004/login
- http://localhost:3004/signup
- http://localhost:3004/reset-password
- http://localhost:3004/verify-email
- http://localhost:3004/invite/[token]
Dev server running on port 3004 (3000 was in use).