Search code examples
reactjsauthenticationsession-variableszustand

Authentication status and private routes bug i cant figure out


im trying to implement zustand for statae management into my app, and im having a problem makind it work with the private routes i allready implemented, the flow is thus:

  1. "authenticated" is stored in session storage, initial false.
  2. Login sets authenticated to true, and private routes are accessible
  3. logout sets it back to false and private routes should be blocked and rediredt to error page

the problem is with the 3. functionality, after logout authenticated in session storage does change to false, but the private routes are still accessible...

Im really confused, here are the releveant files: FetchAuthentication:

import jwtDecode from "jwt-decode";





const handleAauthentication = (result, authenticated) => {

  let decodedJWT = jwtDecode(result);
  console.log(decodedJWT);
  console.log(authenticated);
  sessionStorage.setItem("authenticated", true)
    




}
const FetchAuthentication = (email, password) => {
    var myHeaders = new Headers();
    myHeaders.append("Content-Type", "application/json");
    
    var raw = JSON.stringify({
      "email": email,
      "password": password
    });
    
    var requestOptions = {
      method: 'POST',
      headers: myHeaders,
      body: raw,
      redirect: 'follow'
    };
    
    fetch("xxxxxxxxxxxxxxxxxxx", requestOptions)
      .then(response => response.text())
      .then(result =>  handleAauthentication(result))
      .catch(error => console.log('error', error));
  };

  export {FetchAuthentication};
  export { handleAauthentication };

PrivateRoutes:

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




const PrivateRoutes = () => {

  const authenticated = sessionStorage.getItem('authenticated');
  console.log(authenticated);
  return authenticated ? <Outlet /> : <Navigate to="/*" />;
};

export default PrivateRoutes;

Store:

import { create } from 'zustand';


const store = (set) => ({
  authenticated: sessionStorage.getItem("authenticated") || false,



});

export const useStore = create(store);

relevant part of Login:

  const handleSubmit = async (event) => {
    event.preventDefault(); // Prevents the form submission from refreshing the page
    FetchAuthentication(credentials.email, credentials.password);
  };

relevant part of Navbar:

  const handleLogout = () => {
    sessionStorage.setItem('authenticated', false);
    setSelectedProjectIndex(0);
  };

Any idea may help. Thanks in advance!


Solution

  • I think the problem lies in how the sessionStorage handles the value.

    While you think you passed a boolean, it has been transformed into a string.

    When you query the authenticated parameter, you do not receive false but "false", which is not an empty string, therefore a truthy value.

    The best way would be to delete the param on logout via:

    sessionStorage.removeItem("authenticated");
    

    Making any future call to this parameter be undefined (or maybe null), a falsy value.

    Edit with a quote from MDN: https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API#specifications

    Storage only supports storing and retrieving strings. If you want to save other data types, you have to convert them to strings.