Token used before issued problem! (Time sync?!)

hey I have an architectural question, I am using auth0 in combination with my own API. Setup made after the official documentation how to setup react sdk.

So far so good. Now I want to have an onboarding to ask a user for some more info which is being send to my own backend. So my idea was inside my app I wrap my routes with a user provider which fetches the userinfo from my backend. I also extended the HOC with another withOnboarding HOC which uses the useUser context to decide if user has onboarded or not.

index.tsx

    ReactDOM.render(
      <React.StrictMode>
        <Auth0Provider {...providerConfig}>
          <BrowserRouter>
            <App />
          </BrowserRouter>
        </Auth0Provider>
      </React.StrictMode>,
      document.getElementById("root")
    );

app.tsx

export default function App() {
  const { isLoading, error, isAuthenticated } = useAuth0();

  if (error) {
    return <div>Oops... {error.message}</div>;
  }

  if (isLoading) {
    return <Loading />;
  }

  return (
    <Router>
      <ThemeProvider theme={theme}>
        <UserProvider>
          <CssBaseline />
          {isAuthenticated && <Navbar />}
          <Switch>
            <Route path="/login">
              <LoginPage />
            </Route>
            <ProtectedRoute path="/" exact component={HomePage} />
            <ProtectedRoute path="/profile" component={ProfilePage} />
          </Switch>
        </UserProvider>
      </ThemeProvider>
    </Router>
  );
}

ProtectedRoute.tsx

export const ProtectedRoute = ({
  component,
  ...args
}: React.PropsWithChildren<any>) => (
  <Route
    render={(props) => {
      let Component = withAuthenticationRequired(withOnboarding(component), {});
      return <Component {...props} />;
    }}
    {...args}
  />
);

withOnboarding.tsx

const withOnboarding = <P extends object>(
  Component: ComponentType<P>
): FC<P> => {
  return function WithOnboarding(props: P): JSX.Element {
    const history = useHistory();
    const isOnboarding = history.location.pathname === "/onboarding";
    const { isLoading, isOnboarded } = useUser();
    return isLoading ? (
      <LinearProgress />
    ) : !isOnboarded && !isOnboarding ? (
      <Redirect to="/onboarding" />
    ) : isOnboarded && isOnboarding ? (
      <Redirect to="/" />
    ) : (
      <Component {...props} />
    );
  };
};

userProvider.tsx

const UserProvider = (opts: UserProviderOptions): JSX.Element => {
  const { getAccessTokenSilently } = useAuth0();
  const { children } = opts;
  const [state, dispatch] = useReducer(reducer, initialUserState);
  useEffect(() => {
    (async (): Promise<void> => {
      const token = await getAccessTokenSilently();
      await http
        .authorized(token)
        .get("/rest/v1/users/me")
        .then((result) => {
          console.log(result);
          const user = result.data;
          dispatch({ type: "INITIALISED", user: user });
        })
        .catch(function (error) {
          dispatch({ type: "ERROR", error: loginError(error) });
        });
    })();
  }, [getAccessTokenSilently]);

 

  return (
    <UserContext.Provider
      value={{
        ...state,
        registerUser,
      }}
    >
      {children}
    </UserContext.Provider>
  );
};

All that usually works pretty well, but sometimes (especially when refreshing the page) I get an error about the token is missing or expired. My backend logs say “Token used before issued”! I was googleing it and found things like the time not being synced?!

I dont really know what to do, due to this issue is just occasionally happening… But I wanted to make sure, I handle auth0 and my backend in my project correctly… I was thinking that my user provider maybe tries to fetch the data too early, but when I log the token before the fetch its always present (but maybe wrong?!) On the other hand I kinda make sure in App.tsx that the userProvider will only load after auth0 has finished initialising and isLoading is false?! Anyone an idea?

Hi @gutisAlex,

This could be a clock skew issue.

Take a look at this thread about a similar issue. You can use the leeway param to give some room for clock variance.