0
import React, { useState } from 'react';
import { useHistory } from 'react-router-dom';
import Cookies from 'js-cookie';

const LoginForm = () => {
  const history = useHistory();
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');

  const handleLogin = (e) => {
    e.preventDefault();

    // Form validation goes here

    // Perform login request
    fetch('http://localhost:3001/api/student-login', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        email,
        password,
      }),
    })
      .then((response) => response.json())
      .then((body) => {
        if (body.success) {
          // Successful login. Store the token as a cookie
          Cookies.set('authToken', body.token, {
            path: "localhost:3001/",
            expires: 1,
            sameSite:false
          }); // Expiry set to 1 day

          // Redirect to student page
          history.push('/student');
        } else {
          alert('Log in failed');
        }
      });
  };

  return (
    <>
      <h1>Log In</h1>
      <form id="log-in" onSubmit={handleLogin}>
        <input
          type="email"
          placeholder="Email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
        />
        <input
          type="password"
          placeholder="Password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
        />
        <button type="submit">Log In</button>
      </form>
    </>
  );
};

export default LoginForm;

This is my LoginForm, basically, when user logs in, if all credentials are correct, server side code will create a token. And in here, I store it into cookies, which is then sent to checkIfLoggedInStudent called in StudentPage to check the cookies, get the token stored in it and check if user exists.

MY PROBLEM: basically, when I use credentials="include" the error shows, but when I use credentials="same-origin" the error doesn't show however, isLoggedIn still remains to be equal to false, when supposedly if the cookies was passed correctly, isLoggedIn should equal to true and console.log('req.cookies:', req.cookies); in the function checkIfLoggedInStudent from the controller.js should output the cookies

import React, { useEffect } from 'react';
import { useHistory } from 'react-router-dom';
import Cookies from 'js-cookie';

const StudentPage = () => {
  const history = useHistory();

  useEffect(() => {
    // Check if user is logged in
    const authToken = Cookies.get('authToken');
    console.log('Token exists:', authToken);
    if (!authToken) {
      // User is not logged in, redirect to login page
      history.push('/login');
      console.log('Token DOES NOT exists:', authToken);

    } else {
      // User is logged in, perform additional checks if needed
      fetch('http://localhost:3001/api/checkIfLoggedInStudent', {
        method: "POST",
        mode: "cors",
        credentials: "include",
        headers: {
          "Content-Type": "application/json"
        },
      })
        .then((response) => response.json())
        .then((body) => {
          if (!body.isLoggedIn) {
            // User is not logged in, redirect to login page
            history.push('/login');
          }
        })
        .catch((error) => {
          console.log('Error:', error);
          // Handle error as needed
        });
    }
  }, [history]);

  return (
    <div>
      <h1>Welcome to the Student Page</h1>
      {/* Add your student page content here */}
    </div>
  );
};

export default StudentPage;

here's a snippet from my controller.js file

const studentLogin = async (req, res) => {
  const email = req.body.email.trim();
  const password = req.body.password;

  // Check if email exists
  const user = await Student.findOne({ email })

  //  Scenario 1: FAIL - User doesn't exist
  if (!user) {
    console.log("email does not exist");
    return res.send({ success: false })
  }

  // Check if password is correct using the Schema method defined in User Schema
  user.comparePassword(password, (err, isMatch) => {
    if (err || !isMatch) {
      // Scenario 2: FAIL - Wrong password
      console.log("password are not match");
      return res.send({ success: false });
    }

    // Scenario 3: SUCCESS - time to create a token
    const tokenPayload = {
      _id: user._id
    }

    const token = jwt.sign(tokenPayload, "LOGGED_IN_AS_STUDENT");
    console.log("Generated token:", token);

    // return the token to the client
    return res.send({ success: true, token, username: user.name });
  });
};

const checkIfLoggedInStudent = async (req, res) => {
  console.log('req.cookies:', req.cookies);


  if (!req.cookies || !req.cookies.authToken) {
    // FAIL Scenario 1 - No cookies / no authToken cookie sent
    console.log("no cookies");
    return res.send({ isLoggedIn: false });
  }


  try {
    // try to verify the token
    const tokenPayload = jwt.verify(req.cookies.authToken, 'LOGGED_IN_AS_STUDENT');

    // check if the _id in the payload is an existing user id
    const student = await Student.findById(tokenPayload._id)

    if (student) {
      // SUCCESS Scenario - User is found
      return res.send({ isLoggedIn: true })
    } else {
      // FAIL Scenario 2 - Token is valid but user id not found
      return res.send({ isLoggedIn: false })
    }
  } catch {
    // FAIL Scenario 3 - Error in validating token / Token is not valid
    return res.send({ isLoggedIn: false });
  }
}

here's also my router.js and index.s from the api folder (controller.js is also included in the folder):

updated router.js:

import express from 'express';
import cors from 'cors';

import {
  getStudents,
  getPendingStudents,
  getAdmin,
  getClearanceOfficer,
  studentSignUp,
  studentLogin,
  elevatedUserLogin,
  getAllApplications,
  addApplicationToStudent,
  getStudentApplications,
  checkIfLoggedInStudent,
  checkIfLoggedInElevated,
  getLoggedInStudent,
  approverSignUp
} from './apiController.js';

const app = express();

// Allow Cross Origin Resource Sharing
app.use(cors({ credentials: true, origin: 'http://localhost:3000' }));

app.get("/get-students", getStudents);
app.get("/get-pending-students", getPendingStudents);
app.get("/get-admin", getAdmin);
app.get("/get-clearance-officer", getClearanceOfficer);
app.get("/get-student-applications", getStudentApplications);
app.get("/get-all-applications", getAllApplications);
app.post("/student-signup", studentSignUp);
app.post("/approver-signup", approverSignUp);
app.post("/student-login", studentLogin);
app.post("/elevated-login", elevatedUserLogin);
app.post("/getLoggedInStudent", getLoggedInStudent);
app.post("/checkIfLoggedInStudent", checkIfLoggedInStudent);
app.post("/checkIfLoggedInElevated", checkIfLoggedInElevated);
app.post("/add-application", addApplicationToStudent);

export default app;

index.js:

import express from 'express';
import mongoose from 'mongoose';
import apiRouter from './apiRouter.js';
import fs from 'fs';
import { Approver, BuiltIn, Student } from './apiController.js';

const app = express();
const PORT = 3001;

// Connect to MongoDB
mongoose.connect('mongodb://127.0.0.1:27017/ClearanceApprovalSystem')
  .then(async () => {
    console.log('Connected to MongoDB');
    // Import sample students data
    const sampleStudentsData = fs.readFileSync('./samplestudents.json');
    const students = JSON.parse(sampleStudentsData);
    students.forEach(async (student) => {
      const newStudent = new Student(student);
      await newStudent.save();
    });
    console.log('Sample students imported to the collection.');

    // Import sample builtin data
    const sampleBuiltinData = fs.readFileSync('./samplebuiltin.json');
    const builtins = JSON.parse(sampleBuiltinData);
    builtins.forEach(async (builtin) => {
      const newBuiltin = new BuiltIn(builtin);
      await newBuiltin.save();
    });
    console.log('Sample built-in data imported to the collection.');

    // Import sample builtin data
    const sampleApproverData = fs.readFileSync('./sampleapprovers.json');
    const approvers = JSON.parse(sampleApproverData);
    approvers.forEach(async (approver) => {
      const newApprover = new Approver(approver);
      await newApprover.save();
    });
    console.log('Sample approver data imported to the collection.');
  })
  .catch((error) => {
    console.error('Failed to connect to MongoDB:', error);
  });

// Middleware
app.use(express.json());
app.use(express.urlencoded({ extended: false }));

// API routes
app.use('/api', apiRouter);

// Start the server
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});

Please help! I don't know what to do. This is the error I'm getting from the console:

Error: TypeError: Failed to fetch
    at StudentPage.js:19:1
    at commitHookEffectListMount (react-dom.development.js:23150:1)
    at commitPassiveMountOnFiber (react-dom.development.js:24926:1)
    at commitPassiveMountEffects_complete (react-dom.development.js:24891:1)
    at commitPassiveMountEffects_begin (react-dom.development.js:24878:1)
    at commitPassiveMountEffects (react-dom.development.js:24866:1)
    at flushPassiveEffectsImpl (react-dom.development.js:27039:1)
    at flushPassiveEffects (react-dom.development.js:26984:1)
    at react-dom.development.js:26769:1
    at workLoop (scheduler.development.js:266:1)

Also, I checked Network tab in the Developer Tools and it say CORS error

I added this console.log to the checkIfLoggedInStudent req.cookies: undefined no cookies

  • 1
    What HTTP status code/error message do you get for the failing fetch? – James Jun 02 '23 at 16:06
  • I updated my post and included the error – Steven Universe Jun 02 '23 at 16:12
  • 1
    Are you getting a more complete error message in the browser Developer tools Network tab? Which request is failing, is it /api/student-login or /api/checkIfLoggedInStudent? – James Jun 02 '23 at 16:44
  • its the /api/checkIfLoggedInStudent, basically, when I use credentials="include" the error shows, but when I use credentials="same-origin" the error doesn't show however, isLoggedIn still remains to be equal to false, when supposedly if the cookies was passed correctly, isLoggedIn should equal to true and console.log('req.cookies:', req.cookies); in the function checkIfLoggedInStudent from the controller.js should output the cookies – Steven Universe Jun 02 '23 at 16:57
  • I checked in the Network tab and it says CORS error – Steven Universe Jun 02 '23 at 17:21
  • 1
    Take a look at https://stackoverflow.com/questions/57206675/how-to-fix-cors-error-with-credentials-include – James Jun 02 '23 at 17:24
  • I attached my router.js in which the supposed answer in the link you gave applies, can you show me how it would be applied in my router.js as mine is made differently – Steven Universe Jun 02 '23 at 17:31
  • I did what the answers stated, but same error occurs. maybe I did it wrong, can you show me how can I apply it to my code – Steven Universe Jun 02 '23 at 17:40
  • I don't think `Access-control-allow-origin: *` will work with a credentialed request. [This answer](https://stackoverflow.com/a/55566262/535480) might help – James Jun 02 '23 at 17:51
  • I applied it, yet req.cookies: undefined no cookies still shows, hence its not being passed – Steven Universe Jun 02 '23 at 18:08
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/253933/discussion-between-steven-universe-and-james). – Steven Universe Jun 02 '23 at 18:13

0 Answers0