简体   繁体   中英

Can I keep the token persistent on protected routes?

Sorry if the question is badly phrased. I am working with React.js and Parse Server at school. The issue is the following:

I would like to have protected routes, just for users that are currently logged in, and I am trying to do it by using the .getSessionToken() Parse built-in function. I retrieve the token successfully, get access to the protected routes only if I am logged in, but as soon as I refresh the page, the route is inaccessible again because the token is updated.

I have a working solution, but it creates some issues at the moment. The issue is that even if I have access on the page, there's the following error in the console: No routes matched location "/page1"

Do you have any idea of how I can prevent the token from updating or any other more elegant solution for this issue?

My code is the following:

1.When logging in, I pass a setter using useState() through props, all the way to the App.js where the routes are. The only reason I set the token here is in order to navigate to the next page which is protected.

await Parse.User.logIn(username, password);
const currentUser = Parse.User.current();
const currentToken = currentUser.getSessionToken();
setSessionToken(currentToken);
navigate("/page1");

2.Here, I am checking if a user is currently in my local storage, and if yes, get the token associated with the user.

   //sessionToken = the one I pass with props from step 1
   const [sessionToken, setSessionToken] = useState();
   //This makes sure that I get the token again and again if page is refreshed
   const [refreshedToken, setRefreshedToken] = useState();

   const authenticateUser = async () => {
    if (Parse.User.current() !== null) {
      const token = Parse.User.current().getSessionToken();
      setRefreshedToken(token);
    }
   };

   useEffect(async () => {
    await authenticateUser();
   }, []);

3.Since I have 2 state variables now, I make a conditional rendering by using both.

            <Route
                path="/login"
                element={<LoginPage setSessionToken={setSessionToken} />}
            />
{(sessionToken !== undefined || refreshedToken !== undefined) && (
          <Fragment>
            <Route path="/page1" element={<Page1 />} />
            <Route path="/page2" element={<Page2 />} />
            <Route path="/page3" element={<Page3 />} />

I believe the issue here is that you are attempting to navigate to a path "/page1" before the component rendering the routes knows it should be rendering them, hence the No routes matched location "/page1" error.

You may want to create an AuthWrapper component that checked the sessionStorage and token and renders an Outlet for nested routes you want to protect, otherwise redirect the users to another page, ie to home or login.

import { Outlet, Navigate, useLocation } from 'react-router-dom';

const AuthWrapper = (props) => {
  const location = useLocation();

  ... business logic to check sesstionStorage/token ...

  return (sessionToken !== undefined || refreshedToken !== undefined)
    ? <Outlet />
    : <Navigate to="/login" replace state={{ from: location }} />
};

Now declare the routes, wrapping the routes you want to protect in the AuthWrapper layout component.

<Route
  path="/login"
  element={<LoginPage setSessionToken={setSessionToken} />}
/>
<Route element={<AuthWrapper /* pass any session props here */ />}>
  <Route path="/page1" element={<Page1 />} />
  <Route path="/page2" element={<Page2 />} />
  <Route path="/page3" element={<Page3 />} />
</Route>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM