0

I tried to create an authentication process with ReactJS and Redux/toolkit currently.

When Client enter the page which is required auth, this program would get the value of isAuth from store.authReducer

useEffect(()=>{
 if(!isAuth) navigate("/signin", {replace: true})
},[navigate])

the authentication checker is written in the entry point of router

useEffect(() => {
dispatch(authenticateAsyncAction());
}, [dispatch]);

Suppose, client is logged successfully, and enter any page by the web app element (ex: <Link to="/user/profile">profile</Link>), it works well.

But the problem would happen when client enter the route by browser url input field (ex:https://domain/user/profile). The default value of isAuth is false, and authenticateAsyncAction() is an async function, the navigation will be triggered and redirect page to /signin before isAuth was changed to true.

Is there any way to fix this problem?

Champer Wu
  • 1,101
  • 3
  • 13
  • 32
  • 1
    Does this help answer your question about implementing route protection? https://stackoverflow.com/a/66289280/8690857 Sub in the "authLogin" value with what you select from your Redux store. – Drew Reese Aug 18 '22 at 18:26
  • @DrewReese Actually, I found an official resolution of react-router https://github.com/remix-run/react-router/blob/main/examples/auth/src/App.tsx#L41-L47 – Champer Wu Aug 19 '22 at 10:05

1 Answers1

1

You need to first check for a loading state, which would initially be true. Once the authentication is done, flip the loading state to false and the auth state to true.

Ben Gooding
  • 884
  • 9
  • 18
  • I asked this question in facebook front end community as same time, and I got another answer that suggest me to store the state into `localStorage` – Champer Wu Aug 19 '22 at 10:10
  • How are they currently authenticated? You should not put a session cookie for instance in local storage as it's insecure. You technically could put an `isAuth` boolean in your localstorage, but how would you know if the user is signed out / session has expired? You could server side render your react app and authenticate on the server and pre-populate that field (I'm imagining that is a much more complex solution than you want to do though). – Ben Gooding Aug 19 '22 at 10:32
  • You could also make an checkAuth api call (maybe what you're currently doing), where again you'd need to add in a loading state for the isAuth – Ben Gooding Aug 19 '22 at 10:33
  • Honestly, though you should probably only render most of your components if `isAuth` is true – Ben Gooding Aug 19 '22 at 10:33
  • The best solution is a loading state and only rendering things the non-static portion on your page after that is resolved (or server-side render the auth - much more complex) – Ben Gooding Aug 19 '22 at 10:34
  • 1
    If you're using `next.js` definitely SSR the user! – Ben Gooding Aug 19 '22 at 10:39
  • Yeah, I just store `isAuth` in the `localStorage`. In fact, my authState have a validator like `{ isAuth: boolean, status: 'idle' | 'pending' | 'succeeded' | 'failed'}` if `authState` was changed by any condition, the `statement` would detect the `status` by `redux/toolkit` official resolution https://redux-toolkit.js.org/api/createAsyncThunk – Champer Wu Aug 19 '22 at 12:51
  • Every time, the client side want to access server side API, server side will check the `accessToken` is validated , if not, client side would get error, the frontend program will implement `logout()` function to delete the `isAuth` in `localStorage` and authentication `cookies`. – Champer Wu Aug 19 '22 at 12:59
  • I never used `next.js` before, maybe I can try it ! thx a lot – Champer Wu Aug 19 '22 at 13:03