Authentication
Production Ready
Google OAuth 2.0 authentication is fully implemented with JWT session management and email domain restrictions.
Production Authentication
Google OAuth 2.0
Authentication Flow:
- User visits
https://os.supershyft.capitaland clicks "Sign in with Google" - API redirects to
/api/auth/googlewhich initiates OAuth flow - User authenticates with Google OAuth consent screen
- Google redirects back with authorization code
- API validates email domain (
@capcoib.comorlouis.decuypere@gmail.com) - API creates JWT session token (7-day expiry)
- Sets HttpOnly session cookie (
supershyft_session) - Redirects user to
/home - Subsequent requests include session cookie for authentication
API Endpoints:
GET /api/auth/google- Initiates OAuth flow & handles callbackPOST /api/auth/logout- Clears session cookieGET /api/auth/me- Returns authenticated user infoGET /api/auth/status- Health check for auth system
JWT Payload:
json
{
"sub": "google_123456789",
"email": "louis.decuypere@gmail.com",
"name": "Louis De Cuypere",
"picture": "https://...",
"iat": 1642000000,
"exp": 1642604800
}Backend Middleware:
typescript
// apps/api-worker/src/middleware/auth.ts
export async function authMiddleware(c: Context, next: Next) {
// Production: Extract from session cookie
const sessionCookie = getCookie(c, 'supershyft_session');
if (sessionCookie) {
const payload = await jwt.verify(sessionCookie, c.env.JWT_SECRET);
c.set('userEmail', payload.email);
c.set('user', payload);
}
// Dev: Fall back to X-User-Email header
else {
const devEmail = c.req.header('X-User-Email');
if (devEmail) c.set('userEmail', devEmail);
}
await next();
}Email Domain Restrictions
Only the following email domains are allowed:
@capcoib.com- Team memberslouis.decuypere@gmail.com- Specific allowlist
Attempts to authenticate with other emails will be rejected with a 403 error.
Session Management
Session Cookies:
- Cookie name:
supershyft_session - Duration: 7 days
- HttpOnly: Yes (not accessible via JavaScript)
- SameSite: Lax (CSRF protection)
- Secure: Yes in production (HTTPS only)
Logout:
typescript
// POST /api/auth/logout
fetch('/api/auth/logout', { method: 'POST' })
.then(() => window.location.href = '/')Dev Mode (Local Development)
User Selection
For local development, frontend provides user selector with test accounts:
- louis.decuypere@capcoib.com (Partner)
- alex.rivera@capcoib.com (Analyst)
- sarah.mitchell@capcoib.com (Associate)
Stored in localStorage: supershyft_dev_user_email
API Requests
Frontend sends X-User-Email header on dev requests:
typescript
fetch('/api/companies', {
headers: {
'X-User-Email': localStorage.getItem('supershyft_dev_user_email')
}
})Enabling Dev Mode
- Click "Dev Mode" button in top-right header
- Select a user or enter custom email
- All API requests will use
X-User-Emailheader - No OAuth flow required
Setup Guide
Complete OAuth setup instructions: GOOGLE_OAUTH_SETUP.md
Required Environment Variables:
bash
# .dev.vars (local)
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-client-secret
FRONTEND_URL=http://localhost:5173
JWT_SECRET=random-32-byte-secret
# Production (set via wrangler secret put)
wrangler secret put GOOGLE_CLIENT_ID
wrangler secret put GOOGLE_CLIENT_SECRET
wrangler secret put JWT_SECRETSecurity
Current Implementation:
- ✅ JWT session tokens signed with secret
- ✅ HttpOnly cookies (XSS protection)
- ✅ Email domain restrictions
- ✅ HTTPS enforced in production
- ✅ CORS restricted to whitelisted origins
- ✅ Rate limiting on all routes
- ✅ Automatic user creation on first login
- ✅ 7-day session expiry
Security Headers:
X-Content-Type-Options: nosniffX-Frame-Options: DENYX-XSS-Protection: 1; mode=blockReferrer-Policy: strict-origin-when-cross-originStrict-Transport-Security: max-age=31536000(production)
Rate Limiting:
- High-frequency routes: 100 req/min
- AI operations: 50 req/min
- Bulk actions: 5 req/min
Troubleshooting
"Unauthorized" errors
- Check session cookie is present in browser DevTools
- Verify JWT_SECRET is set correctly
- Check cookie hasn't expired (7 days)
- Try logging out and back in
OAuth redirect fails
- Verify
FRONTEND_URLmatches your frontend URL - Check Google OAuth redirect URIs in Google Cloud Console
- Ensure
GOOGLE_CLIENT_IDandGOOGLE_CLIENT_SECRETare set
Email not allowed
- Only
@capcoib.comandlouis.decuypere@gmail.comare allowed - Contact admin to add your email domain
Dev mode not working
- Check
X-User-Emailheader is being sent - Verify localStorage has
supershyft_dev_user_emailset - Ensure API worker is running locally