Reputation: 1
ProtectedRoute.js
import { Navigate } from 'react-router-dom';
import Cookies from 'js-cookie';
import { checkToken } from './auth';
import Admin from '../pages/Admin-page/Admin';
const ProtectedRoute = () => {
const [isLoading, setIsLoading] = useState(true);
const [isValid, setIsValid] = useState(false);
useEffect(() => {
const verifyToken = async () => {
try {
const valid = await checkToken();
console.log('Token valid:', valid); // Debugging
setIsValid(valid);
} catch (error) {
console.error('Error validating token:', error);
setIsValid(false);
} finally {
setIsLoading(false);
}
};
verifyToken();
}, []);
if (isLoading) {
return <div>Loading...</div>;
}
console.log('Token isvalid:', isValid); // Debugging
return isValid ? <Admin /> : <Navigate to="/login" replace />;
};
export default ProtectedRoute;
App.js
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Login from './authentications/Login';
import Users from './pages/Side-menu/Users';
import Hours from './pages/Side-menu/Hours';
import Tenants from './pages/Side-menu/Tenants';
import ResetPassword from './authentications/ResetPassword';
import NewPassword from './authentications/NewPassword';
import ProtectedRoute from './authentications/ProtectedRoute';
import PostContent from './pages/Admin-page/PostContent';
import Admin from './pages/Admin-page/Admin';
import Home from './pages/Side-menu/Home';
import Signup from './authentications/Signup';
function App() {
return (
<Router>
<Routes>
<Route path="/login" element={<Login />} />
<Route path="/signup" element={<Signup />} />
<Route path="/forgotpassword" element={<ResetPassword />} />
<Route path="/newpassword" element={<NewPassword />} />
{/* Protected routes */}
<Route
path="/"
element={
<ProtectedRoute>
<Admin />
</ProtectedRoute>
}
>
<Route path="admin/posts" element={<PostContent />} />
<Route path="admin/users" element={<Users />} />
<Route path="admin/hours" element={<Hours />} />
<Route path="admin/tenants" element={<Tenants />} />
</Route>
</Routes>
</Router>
);
}
export default App;
Login.js
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useTranslate } from '@tolgee/react';
import { LanguageSelect } from '../LanguageSelect';
import { checkToken } from './auth';
import axios from 'axios';
import Cookies from 'js-cookie';
function Login() {
const [formData, setFormData] = useState({
email: '',
password: '',
});
const [errors, setErrors] = useState({ password: '' });
const navigate = useNavigate(); // Přidání useNavigate hooku
const { t } = useTranslate();
const handleInputChange = (e) => {
const { name, value } = e.target;
setFormData({ ...formData, [name]: value });
};
const validatePassword = (password) => {
const regex = /^(?=.*[A-Z])(?=.*\d)[A-Za-z\d@#$%^&+=!]{8,}$/; // Updated regex
return regex.test(password);
};
const handleLogin = async (e) => {
e.preventDefault();
if (!validatePassword(formData.password)) {
setErrors({
password:
'Password must be at least 8 characters long, contain at least one uppercase letter and one number.',
});
return;
}
try {
const response = await axios.post(
'https://MYWEBSITE/api/v1/users/login',
{
email: formData.email,
password: formData.password,
},
{
headers: {
'Content-Type': 'application/json',
},
withCredentials: true, // Added withCredentials setting
}
);
if (response.status === 200) {
console.log('Login successful.');
setFormData({
email: '',
password: '',
});
const isValidToken = await checkToken();
if (isValidToken) {
console.log('Token is valid, navigating to homepage.');
navigate('/'); // Redirect after successful login
} else {
console.error('Invalid token after login.');
}
} else {
console.error('Error logging in:', response.statusText);
}
} catch (error) {
console.error('Axios error:', error);
}
};
export default Login;
auth.js:
import axios from 'axios';
export const checkToken = async () => {
try {
const response = await axios.get(
'https://MYWEBSITE/api/v1/users/checkToken',
{
headers: {
'Content-Type': 'application/json',
},
withCredentials: true,
}
);
return response.data.status === 'success';
} catch (error) {
if (error.response) {
console.error('Server error:', error.response.data);
return false;
} else if (error.request) {
console.error('Network error:', error.request);
return false;
} else {
console.error('Request error:', error.message);
return false;
}
}
};
I use protected routes in ReactJS and it correctly checks the validity of the token, but it still redirects me back to Login and not to the homepage, which is Admin.js. I tried use <Outlet/> in my Protected Route, but it didn't work. In the console I check if the token is validated correctly and I have no problem there. I've been sitting on this for a long time and haven't found a solution on any platform. It's possible that I have a bug somewhere in App.js, because I'm working with Protected Route for the first time and I don't know if I've written it correctly.
Upvotes: 0
Views: 39
Reputation: 21
you can work with passport.js: server :
import express from 'express';
import passport from 'passport';
import jwt from 'jsonwebtoken';
import dotenv from 'dotenv';
dotenv.config();
const router = express.Router();
const { CLIENT_URL } = process.env;
// Initial route to start the authentication process
router.get('/google',
passport.authenticate('google', { scope: ['profile', 'email', 'openid'] })
);
// Callback route that Google redirects to after authentication
router.get('/google/callback',
passport.authenticate('google', { failureRedirect: '/login', session: false }),
(req, res) => {
if (!req.user) {
return res.redirect('/login');
}
// Create JWT token
const token = jwt.sign({ userId: req.user.googleId }, process.env.JWT_SECRET, { expiresIn: '1h' });
// Set token as HTTP-only cookie
res.cookie('token', token, { httpOnly: true });
// Create a user profile object
const userProfile = {
googleId: req.user.googleId,
displayName: req.user.name,
email: req.user.email,
picture: req.user.picture,
};
// Redirect to client with user profile in URL
// res.redirect(`${CLIENT_URL}/?profile=${encodeURIComponent(JSON.stringify(userProfile))}`);
res.redirect(`${CLIENT_URL}/messenger?profile=${encodeURIComponent(JSON.stringify(userProfile))}`);
}
);
export default router;
client:
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import AccountProvider from './context/AccountProvider';
//components:
import Messenger from './components/Messenger';
export const App = () => {
return (
<Router>
<AccountProvider>
<Routes>
<Route path="/" element={<Messenger />} />
<Route path="/messenger" element={<Messenger />} />
</Routes>
</AccountProvider>
</Router>
);
};
export default App;
Upvotes: 0