This is my first question.
I am self-studying React.js, Node.js, and Express. For this reason, I am trying to create my own website where a user can register, log in, and access the page with their data only if the login is successful.
If the login is successful, a token is created using the user’s email as the payload. Additionally, I want to use a Higher Order Component (HOC)
Protect.js
import React, { useState, useEffect } from 'react';
import { Navigate } from 'react-router-dom';
import axios from 'axios';
const Protect = ({ component: Component }) => {
const [authenticated, setAuthenticated] = useState(false);
useEffect(() => {
const checkAuth = async () => {
try {
const response = await axios.get('http://localhost:5000/checkAuth', { withCredentials: true });
console.log('Protected GET Response:', response.data);
if (response.status === 200) {
setAuthenticated(true);
} else {
setAuthenticated(false);
}
} catch (error) {
console.error('Protect: Error during auth', error.response);
setAuthenticated(false);
}
};
checkAuth();
}, []);
return authenticated ? <Component /> : <Navigate to="/Login" />;
};
export default Protect;
so that in my App.js
file, I have something like:
<Route
path="/ProtectedPage"
element={<Protect component={<ProtectedPage />} />}
/>
In the handleFormSubmit
function of FormLogin
, I added
const handleFormSubmit = async (event) => {
event.preventDefault();
const formData = {
email: email,
password: password,
};
try {
const response = await axios.post('http://localhost:5000/login', formData, { withCredentials: true });
console.log("Client: Server Says: ", response.data);
console.log("Client: Login OK");
navigate('/ProtectedPage');
} catch (error) {
console.log('Server Error:', error);
}
};
It might be useful to know that Protected
makes a GET request to
const verifyToken = (req, res, next) => {
const token = req.cookies.token;
if (!token) {
res.status(401).send('Access Denied');
} else {
jwt.verify(token, secret, function (err, decoded) {
if (err) {
res.status(401).send('No Valid Token!');
} else {
req.email = decoded.email;
req.token = token;
console.log('verifyToken: ', req.email);
next();
}
});
}
};
app.get('/checkAuth', verifyToken, (req, res) => {
res.sendStatus(200).send({ authenticated: true, email: req.email, token: req.token});
});
You can view my code at this link: https://github.com/CiccioLagXCVIII/MyOwnSite.git
But even if the login is successful, I don’t get any errors or redirection to /ProtectedPage
Thanks to anyone who will respond.
I have already tried using console.log
to verify if the data is received and sent correctly, and it is. My issue is that I don’t see any errors (I only see the logs that I have entered myself for debugging) in the console when the login is successful, but the redirection doesn’t happen.
2
Answers
First just a clarification on nomenclature:
Protect
isn’t a Higher Order Component, e.g. it’s not a function that takes a React component as an argument and returns a decorated React component, it is just a regular React component that takes acomponent
prop.The issue is that
Protect
uses an initialauthenticated
value that matches unauthenticated users and on the initial render will redirect users to the"/login"
route.Start from an "unknown" authentication state and wait for the
checkAuth
code to complete and update theauthenticated
state prior to rendering the protected content or redirecting.Example:
i think you have imported useNavigate hook, if not must import. and if don’t work you can try this.