Home > Enterprise >  How can I logout user on route change once JWT token is expired?
How can I logout user on route change once JWT token is expired?

Time:12-27

I'm using Passport JWT and I want to check JWT token validity to perform a logout if it's already expired. I already made it work on page refresh but not on route change (from navbar, for example). I need to find a way to check it every time any route component is re-rendered, and I know it's very likely that I don't need to do it on every single component. I just don't know how.

Here's the code that's working for page refresh:

On Express

authenticated.js

router.route("/").get((req, res) => {
  passport.authenticate("jwt", { session: false }, (err, user, info) => {
    if (!user) {
      res.status(401);
      res.send("Unauthorized")
    }
  })(req, res);
});

module.exports = router;

On React

AuthContext.js

export const AuthContext = createContext();

function AuthProvider({ children }) {
  const [isLoaded, setIsLoaded] = usePersistedState(false, "loaded");
  const [user, setUser] = usePersistedState(null, "username");
  const [isAuthenticated, setIsAuthenticated] = usePersistedState(
    false,
    "auth"
  );

  useEffect(() => {
    axios
      .get("/authenticated")
      .then((response) => {
        return;
      })
      .catch((error) => {
        setUser("");
        setIsAuthenticated(false);
        setIsLoaded(true);
      });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return (
    <div>
      {!isLoaded ? (
        <h3>Loading...</h3>
      ) : (
        <AuthContext.Provider
          value={{ user, setUser, isAuthenticated, setIsAuthenticated }}
        >
          {children}
        </AuthContext.Provider>
      )}
    </div>
  );
}

export default AuthProvider;

index.js

ReactDOM.render(
  <AuthProvider>
    <App />
  </AuthProvider>,
  document.getElementById("root")
);

UPDATE

I tried to get it done by adding this useEffect function on my PrivateOutlet.js, which handles the private routes, but it didn't work:

function PrivateOutlet() {
  const authContext = useContext(AuthContext);

  const location = useLocation();

  useEffect(() => {
    axios
      .get("/authenticated")
      .then((response) => {
        return;
      })
      .catch((err) => {
        authContext.setIsAuthenticated(false);
        authContext.setUser("");
      });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [location]);

  return authContext.isAuthenticated ? (
    <Outlet />
  ) : (
    <Navigate to="/login" replace state={{ path: location.pathname }} />
  );
}

export default PrivateOutlet;

CodePudding user response:

The response is not specific to any platform/language. In general, the authentication provider/service is issuing the token to the client. The token meant for accessing the private resoruces upon validating by resouce server. As you're using the JWT token, so a resouce server/service can validate the token without talking to authentication service or without performing a database look-up. Your server side code always need to validate the token with the incoming requests, which you can do by creating an interceptor for protected requests. In short, you can invoke call from client to validate the token whenever required.

CodePudding user response:

it could be a socket call for the checking through a wrapper component. If the socket returns false, then history.push him into a page where the login is not required

  • Related