# ๐Ÿ”ง Resend OTP Fix - Public Endpoint ## ๐Ÿ› **Problem:** Resend OTP endpoint was failing with `ERR_CONNECTION_REFUSED` because: 1. The entire `OtpController` has `@UseGuards(AuthGuard)` at class level 2. The resend endpoint requires a temp token, not a full JWT 3. AuthGuard was rejecting the request ## โœ… **Solution:** Made the resend endpoint public by: 1. Adding `@Public()` decorator 2. Updating `AuthGuard` to respect public routes 3. Endpoint verifies temp token manually --- ## ๐Ÿ“ **Changes Made:** ### 1. **Updated OtpController** (`otp.controller.ts`): ```typescript // 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`): ```typescript 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('isPublic', [ context.getHandler(), context.getClass(), ]); if (isPublic) { return true; // Skip authentication } return super.canActivate(context); } } ``` --- ## ๐Ÿ”„ **How It Works:** 1. **Frontend** calls `/api/otp/email/resend` with temp token 2. **AuthGuard** checks for `@Public()` decorator 3. **If public**: Skips JWT validation, allows request through 4. **Endpoint** manually verifies temp token 5. **Extracts** userId from temp token 6. **Sends** OTP email 7. **Returns** success --- ## ๐Ÿงช **Testing:** ### **Test Resend:** 1. โœ… Login with email OTP enabled 2. โœ… On OTP page, wait 30 seconds 3. โœ… Click "Resend Code" 4. โœ… **Should work now!** 5. โœ… Check console for new OTP code 6. โœ… Enter code and login --- ## โš ๏ธ **Current Status:** Backend needs to restart to apply changes. If backend is not responding: ```bash # Kill existing process pkill -f "nest start" # Restart cd apps/api npm run dev ``` --- ## ๐Ÿ“Š **Files Modified:** 1. **`apps/api/src/otp/otp.controller.ts`** - Added `Public` decorator - Marked `email/resend` as public - Injected `JwtService` 2. **`apps/api/src/auth/auth.guard.ts`** - Injected `Reflector` - Added public route check - Skip auth for public routes 3. **`apps/web/src/components/pages/OtpVerification.tsx`** - Already updated to use `/api/otp/email/resend` --- **Once backend restarts, resend should work!** ๐Ÿš€