- 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
3.0 KiB
3.0 KiB
🔧 Resend OTP Fix - Public Endpoint
🐛 Problem:
Resend OTP endpoint was failing with ERR_CONNECTION_REFUSED because:
- The entire
OtpControllerhas@UseGuards(AuthGuard)at class level - The resend endpoint requires a temp token, not a full JWT
- AuthGuard was rejecting the request
✅ Solution:
Made the resend endpoint public by:
- Adding
@Public()decorator - Updating
AuthGuardto respect public routes - Endpoint verifies temp token manually
📝 Changes Made:
1. Updated OtpController (otp.controller.ts):
// Added Public decorator
export const IS_PUBLIC_KEY = 'isPublic';
export const Public = () => SetMetadata(IS_PUBLIC_KEY, true);
// Marked resend endpoint as public
@Public()
@Post('email/resend')
async resendEmailOtp(@Body() body: { tempToken: string }) {
try {
// Verify temp token manually
const payload = this.jwtService.verify(body.tempToken);
if (!payload.temp) {
throw new UnauthorizedException('Invalid token type');
}
const userId = payload.userId || payload.sub;
// Send OTP
return this.otpService.sendEmailOtp(userId);
} catch (error) {
throw new UnauthorizedException('Invalid or expired token');
}
}
2. Updated AuthGuard (auth.guard.ts):
import { Reflector } from '@nestjs/core';
@Injectable()
export class AuthGuard extends PassportAuthGuard('jwt') {
constructor(private reflector: Reflector) {
super();
}
canActivate(context: ExecutionContext) {
// Check if route is marked as public
const isPublic = this.reflector.getAllAndOverride<boolean>('isPublic', [
context.getHandler(),
context.getClass(),
]);
if (isPublic) {
return true; // Skip authentication
}
return super.canActivate(context);
}
}
🔄 How It Works:
- Frontend calls
/api/otp/email/resendwith temp token - AuthGuard checks for
@Public()decorator - If public: Skips JWT validation, allows request through
- Endpoint manually verifies temp token
- Extracts userId from temp token
- Sends OTP email
- Returns success
🧪 Testing:
Test Resend:
- ✅ Login with email OTP enabled
- ✅ On OTP page, wait 30 seconds
- ✅ Click "Resend Code"
- ✅ Should work now!
- ✅ Check console for new OTP code
- ✅ Enter code and login
⚠️ Current Status:
Backend needs to restart to apply changes. If backend is not responding:
# Kill existing process
pkill -f "nest start"
# Restart
cd apps/api
npm run dev
📊 Files Modified:
-
apps/api/src/otp/otp.controller.ts- Added
Publicdecorator - Marked
email/resendas public - Injected
JwtService
- Added
-
apps/api/src/auth/auth.guard.ts- Injected
Reflector - Added public route check
- Skip auth for public routes
- Injected
-
apps/web/src/components/pages/OtpVerification.tsx- Already updated to use
/api/otp/email/resend
- Already updated to use
Once backend restarts, resend should work! 🚀