SPRINT 3 ‐ OTP VERIFICATION (Reset Password) - BlueJayBird11/UniJet GitHub Wiki

User Story: As a user, I have an option to reset my password incase I forget it.

About

While resetting your password, you are sent a One-Time-Password (OTP) to your email, to verify your email authenticity.

Usage

To reset your password, you press the Reset it link on the login page:

image

After that, you will be prompted to page that asks for email associated with the account. You enter your email address and press send.

image

After that, you get your OTP in your email:

image

Users are then asked to provide the associated email address and the OTP to verify their account.

image

If verified successfully, users will then receive an alert saying verified successfully and are then prompted to a page where they can change their password.

image

image

If the verification fails due to wrong credentials used while verifying, it will show error and does not let the user change their password.

image

Workings

The inner working of these features are divided into two parts, backend and frontend.

backend

The backend working for generating and sending OTP are located in ForgotPassword.ts inside backend_ts. We are using nodemailer & dotenv to send emails. The .env file is not to be pushed in github repo for public use. This is the snippet of code tasked with generating OTP and sending the email:

    this.router.post('/send-otp', async (req, res) => {
        // req: { body: { email: any; }; }, res: { json: (arg0: { message: string; }) => void; status: (arg0: number) => { (): any; new(): any; json: { (arg0: { error: string; }): void; new(): any; }; }; }
        const email = req.body.email;
        const otp = Math.floor(100000 + Math.random() * 900000).toString(); // 6 digit OTP
        otpDatabase[email] = otp; // Store OTP
    
        try {
            console.log(email)
            await transporter.sendMail({
                from: process.env.EMAIL_USER,
                to: email,
                subject: 'Your OTP',
                text: `Your OTP is: ${otp}`,
            });
            res.json({ message: 'OTP sent successfully.' });
        } catch (error) {
            console.error('Error sending email:', error);
            res.status(500).json({ error: 'Failed to send OTP.' });
        }
    });

And this is the snippet of code tasked with verifying the OTP and the email address:

    this.router.post('/verify-otp', (req, res) => {
        // req: { body: { email: any; otp: any; }; }, res: { json: (arg0: { message: string; }) => void; status: (arg0: number) => { (): any; new(): any; json: { (arg0: { error: string; }): void; new(): any; }; }; }
        // const { email, otp } = req.body;
        const email = req.body.email;
        const otp = req.body.otp
        if (otpDatabase[email] && otpDatabase[email] === otp) {
            // OTP matches
            delete otpDatabase[email]; // Consider deleting the OTP after successful verification
            res.json({ message: 'OTP verified successfully.' });
        } else {
            // OTP does not match
            res.status(400).json({ error: 'OTP verification failed.' });
        }
    });

frontend

There are three files associated with resetting password, all three files are located in Unijet/frontend/src/scenes/loginAndSignup/ The ForgotPasswordPage.tsx takes the email provided by the user and calls the backend to send the email.

      // Call backend API to send OTP
      axios.post('http://localhost:8000/api/send-otp', { email })
          .then((response) => {
              // Assuming the backend sends a success message
              console.log(response.data.message);
              alert("If the email is registered with us, you will receive an OTP.");
              // Navigate to OTP verification page
              navigate('/otpverificationpage');
          })
          .catch((error) => {
              console.error("Error sending OTP:", error);
              alert("Failed to send OTP. Please try again.");
          });

The OTPVerificationPage.tsx asks user for their email address and their OTP to verify the authenticity, it calls backend to verify OTP.

    const verifyOtp = async () => {
        axios.post('http://localhost:8000/api/verify-otp', { email, otp })
            .then((response) => {
                // Handle successful OTP verification
                alert("OTP verified successfully.");
                navigate('/change-password'); // Adjust this as necessary
            })
            .catch((error) => {
                // Handle error in OTP verification
                console.error("Error verifying OTP:", error);
                alert("Failed to verify OTP. Please try again.");
            });
    };

Finally, after being successfully verified, users are then prompted to ChangePasswordPage.tsx from where they can change their password.