The React SPA I am working on is using React Query, Ory (as auth provider) and React Router. A typical pattern I need to implement is the following:
- User not logged in and goes to /login -> no redirect
- User not logged in and goes to /signup -> no redirect
- User logged in and goes to /login -> redirect to /home
- User logged in and goes to /signup -> redirect to /home
- User logged in, is in step X of onboarding and goes to any page -> redirect to step X
- User logged in, is fully onboarded and goes to /login or /signup -> redirect to /home
- User logged in, is fully onboarded and goes to any page not (/login or /signup) -> redirect to targeted page
There are several ways to check if a user is logged in:
- Proactively, using for instance Ory’s “whoami” API (concretely, it makes a call to their server and responds with 200 if the cookie is a valid authentication proof and 401 otherwise).
- Reactively, if any API call to my backend responds with 401.
I have implemented in the React Query cache the following logic:
const queryClient = new QueryClient({
queryCache: new QueryCache({
onError: (error) => {
if (error?.statusCode === 401) {
if (
error?.url != "ory-session" &&
error?.url != "login" &&
error?.url != "logout"
) {
/* Cannot use React Router because QueryClientProvider is above BrowserRouter in the component tree */
if (!window.location.pathname.includes("/login")) {
window.history.pushState({}, "", "/login");
window.location.reload();
}
}
}
},
}),
On the other hand, I have tried the following:
- Create a custom hook that manages the onboarding step + redirection if already logged in
- Create a component “RedirectWhenLoggedIn” on top of /login and /signup
- Create a component “RedirectOnboarding” on top of any other page
However, this creates messy redirections and race conditions with React Query (especially when “logging out” or when checking the current onboarding step of the user – which is based on server state).
This is a quite typical pattern request: what is the best practice for implementing it?