- Remove OtpGateGuard from transactions controller (OTP verified at login) - Fix categories controller to use authenticated user instead of TEMP_USER_ID - Add comprehensive implementation plan document - Update .env.example with WEB_APP_URL - Prepare for admin dashboard development
4.8 KiB
✅ Email OTP Sending During Login - FIXED
🐛 Problem:
Email OTP was not being sent during login flow. It only worked when manually requested from the profile page.
Symptoms:
- User logs in with email/password (has email OTP enabled)
- Redirected to OTP page
- No email received
- Console shows no OTP code
- User stuck on OTP page
✅ Root Cause:
The login flow was checking if OTP was required and returning a temp token, but never actually sending the email OTP!
// OLD CODE - No email sent!
if (requiresOtp) {
return {
requiresOtp: true,
availableMethods: {
email: user.otpEmailEnabled,
totp: user.otpTotpEnabled,
},
tempToken: this.generateTempToken(user.id, user.email),
};
}
✅ Fixes Applied:
1. Injected OtpService into AuthService ✅
// auth.module.ts
imports: [
PrismaModule,
PassportModule,
forwardRef(() => OtpModule), // Added OtpModule
JwtModule.register({...}),
],
// auth.service.ts
constructor(
private readonly prisma: PrismaService,
private readonly jwtService: JwtService,
@Inject(forwardRef(() => OtpService)) // Injected OtpService
private readonly otpService: OtpService,
) {}
2. Send Email OTP During Login ✅
// In login() method
if (requiresOtp) {
// Send email OTP if enabled
if (user.otpEmailEnabled) {
try {
await this.otpService.sendEmailOtp(user.id); // ← SEND EMAIL!
} catch (error) {
console.error('Failed to send email OTP during login:', error);
// Continue anyway - user can request resend
}
}
return {
requiresOtp: true,
availableMethods: {
email: user.otpEmailEnabled,
totp: user.otpTotpEnabled,
},
tempToken: this.generateTempToken(user.id, user.email),
};
}
3. Send Email OTP During Google Login ✅
// In googleLogin() method
if (requiresOtp) {
// Send email OTP if enabled
if (user.otpEmailEnabled) {
try {
await this.otpService.sendEmailOtp(user.id); // ← SEND EMAIL!
} catch (error) {
console.error('Failed to send email OTP during Google login:', error);
}
}
return {
requiresOtp: true,
availableMethods: {...},
tempToken: this.generateTempToken(user.id, user.email),
};
}
4. Added Separate Verification Method ✅
Created verifyEmailOtpForLogin() that verifies the code without enabling the feature:
// otp.service.ts
async verifyEmailOtpForLogin(userId: string, code: string): Promise<boolean> {
const stored = this.emailOtpStore.get(userId);
if (!stored || new Date() > stored.expiresAt || stored.code !== code) {
return false;
}
this.emailOtpStore.delete(userId);
return true;
}
5. Updated Login Verification ✅
// In verifyOtpAndLogin() method
if (method === 'email') {
const isValid = await this.otpService.verifyEmailOtpForLogin(userId, otpCode);
if (!isValid) {
throw new UnauthorizedException('Invalid or expired email OTP code');
}
}
📝 Files Modified:
-
apps/api/src/auth/auth.module.ts- Added
forwardRef(() => OtpModule)to imports
- Added
-
apps/api/src/auth/auth.service.ts- Injected
OtpService - Send email OTP in
login()method - Send email OTP in
googleLogin()method - Use
verifyEmailOtpForLogin()for verification
- Injected
-
apps/api/src/otp/otp.service.ts- Added
verifyEmailOtpForLogin()method - Keeps existing
verifyEmailOtp()for setup
- Added
🧪 Testing:
Test Email/Password Login with Email OTP:
- ✅ Login with email/password
- ✅ Email OTP should be sent automatically
- ✅ Check console for:
📧 OTP Code for user@example.com: 123456 - ✅ Enter code on OTP page
- ✅ Should login successfully
Test Google Login with Email OTP:
- ✅ Click "Continue with Google"
- ✅ Authenticate
- ✅ Email OTP should be sent automatically
- ✅ Redirected to OTP page
- ✅ Check console for OTP code
- ✅ Enter code
- ✅ Should login successfully
✨ What Now Works:
✅ Email OTP sent during login - Automatically when user has it enabled
✅ Email OTP sent during Google OAuth - Works for both flows
✅ Proper verification - Uses dedicated login verification method
✅ Console logging - Shows OTP code in development
✅ Webhook integration - Sends to n8n if configured
🎯 Expected Behavior:
- User logs in (email/password or Google)
- If email OTP enabled:
- Email is sent automatically
- Console shows:
📧 OTP Code for user@example.com: 123456 - User redirected to OTP page
- User enters code
- Code verified
- User logged in successfully
Email OTP should now work during login! Test it now! 🚀