feat: remove OTP gate from transactions, fix categories auth, add implementation plan
- 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
This commit is contained in:
190
EMAIL_OTP_FIX.md
Normal file
190
EMAIL_OTP_FIX.md
Normal file
@@ -0,0 +1,190 @@
|
||||
# ✅ 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**!
|
||||
|
||||
```typescript
|
||||
// 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** ✅
|
||||
```typescript
|
||||
// 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** ✅
|
||||
```typescript
|
||||
// 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** ✅
|
||||
```typescript
|
||||
// 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:
|
||||
|
||||
```typescript
|
||||
// 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** ✅
|
||||
```typescript
|
||||
// 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:**
|
||||
|
||||
1. **`apps/api/src/auth/auth.module.ts`**
|
||||
- Added `forwardRef(() => OtpModule)` to imports
|
||||
|
||||
2. **`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
|
||||
|
||||
3. **`apps/api/src/otp/otp.service.ts`**
|
||||
- Added `verifyEmailOtpForLogin()` method
|
||||
- Keeps existing `verifyEmailOtp()` for setup
|
||||
|
||||
---
|
||||
|
||||
## 🧪 **Testing:**
|
||||
|
||||
### Test Email/Password Login with Email OTP:
|
||||
1. ✅ Login with email/password
|
||||
2. ✅ **Email OTP should be sent automatically**
|
||||
3. ✅ Check console for: `📧 OTP Code for user@example.com: 123456`
|
||||
4. ✅ Enter code on OTP page
|
||||
5. ✅ Should login successfully
|
||||
|
||||
### Test Google Login with Email OTP:
|
||||
1. ✅ Click "Continue with Google"
|
||||
2. ✅ Authenticate
|
||||
3. ✅ **Email OTP should be sent automatically**
|
||||
4. ✅ Redirected to OTP page
|
||||
5. ✅ Check console for OTP code
|
||||
6. ✅ Enter code
|
||||
7. ✅ 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:**
|
||||
|
||||
1. User logs in (email/password or Google)
|
||||
2. If email OTP enabled:
|
||||
- Email is sent automatically
|
||||
- Console shows: `📧 OTP Code for user@example.com: 123456`
|
||||
- User redirected to OTP page
|
||||
3. User enters code
|
||||
4. Code verified
|
||||
5. User logged in successfully
|
||||
|
||||
**Email OTP should now work during login! Test it now!** 🚀
|
||||
Reference in New Issue
Block a user