OTP Verification for First User - Documentation
Overview
Added OTP (One-Time Password) verification for the first user of new enterprise organizations to prevent domain squatting attacks.
Security Problem Solved
Without OTP: Someone could register as fake.user@amazon.com and claim the entire Amazon organization before real Amazon employees join.
With OTP: The first person to register with an enterprise email domain must verify email ownership through OTP before becoming admin.
How It Works
1. Registration Flow for First User (New Enterprise Org)
When a user registers with a company email (e.g., john@company.com) and creates a new organization:
- Backend generates OTP: 6-digit code stored in memory
- OTP displayed on screen: For testing (later can send via email)
- User enters OTP: Frontend verification screen
- Account activated: User becomes Admin after successful verification
2. Registration Flow for Subsequent Users (Existing Org)
When additional users join an existing organization:
- No OTP required (org already claimed)
- Account goes to pending status
- Requires admin approval
3. Individual Account Registration
Personal accounts (gmail, yahoo, etc.):
- No OTP required
- Instant approval as admin
Files Modified
Backend
src/lib/otp-manager.ts- NEW- OTP generation (6-digit random)
- In-memory storage with expiration
- Verification with attempt limiting (max 5)
- Auto-cleanup of expired OTPs
src/app/api/auth/route.ts- UPDATED- Added
verify_otpaction - Modified registration flow to check if org is new
- Returns
requiresOTP: truefor first enterprise user - Displays OTP in response (testing mode)
- Added
Frontend
src/app/login/page.tsx- UPDATED- Added OTP verification UI state
- New screen: "🔐 Verify Your Email"
- Displays OTP prominently for testing
- Auto-login after successful verification
- Redirects to dashboard after 2 seconds
OTP Features
Security
- ✅ Expiration: 10 minutes validity
- ✅ Attempt Limiting: Max 5 attempts before OTP is invalidated
- ✅ One-time use: OTP deleted after successful verification
- ✅ Email-bound: OTP tied to specific email address
Testing Mode
- 🔑 OTP displayed on screen in blue box
- Shows email and expiration info
- Remove
otpfield from API response in production
User Experience
text
1. User fills registration form
2. Clicks "Create User"
3. Sees OTP verification screen with:
- Organization name they're claiming
- OTP code displayed (testing)
- Input field for OTP entry
4. Enters OTP
5. Clicks "Verify & Become Admin"
6. Auto-logged in and redirected to dashboardAPI Endpoints
POST /api/auth - Register
Request:
json
{
"action": "register",
"id": "john",
"name": "John Doe",
"email": "john@newcompany.com",
"password": "SecurePass123",
"accountType": "enterprise"
}Response (if OTP required):
json
{
"requiresOTP": true,
"email": "john@newcompany.com",
"organizationName": "newcompany.com",
"otp": "123456",
"message": "Verification required..."
}POST /api/auth - Verify OTP
Request:
json
{
"action": "verify_otp",
"email": "john@newcompany.com",
"otp": "123456"
}Response:
json
{
"success": true,
"user": { ... },
"organization": { ... },
"message": "Organization created. You are the Admin."
}Server Logs
text
[OTP] Generated for john@newcompany.com: 123456 (expires in 10 minutes)
[Auth] OTP required for first user of org "newcompany.com"
[Auth] OTP verified! User john@newcompany.com is now Admin of "newcompany.com"Production Deployment
Remove Testing Display
In production, remove the OTP from API response:
typescript
// src/app/api/auth/route.ts
return NextResponse.json({
requiresOTP: true,
email: userData.email,
organizationName: org.name,
// otp: otp, // REMOVE THIS LINE
message: `Verification code sent to ${userData.email}`
});Add Email Integration
Replace the OTP display with email sending:
typescript
import { sendOTPEmail } from '@/lib/email-service';
const otp = createOTP(userData.email, org.id, newUserData);
await sendOTPEmail(userData.email, otp, org.name);Benefits
- ✅ Prevents Domain Squatting: Malicious users can't claim organizations
- ✅ Email Verification: Proves email ownership
- ✅ Security Layer: Additional protection for admin account creation
- ✅ User-friendly: Simple 6-digit code, clear UI
- ✅ Testable: OTP visible on screen during development
Future Enhancements
- Email Integration: Send OTP via email (SendGrid, AWS SES, etc.)
- SMS Option: Phone number verification as alternative
- Resend OTP: Add resend button with cooldown timer
- Rate Limiting: Prevent spam registration attempts
- Database Storage: Move from in-memory to Redis for persistence
- 2FA Option: Allow users to enable 2FA after account creation