Using @auth0/auth0-react and getAccessTokenSilently in useEffect leads to infinite loop

Hi team,

I am following the React Authentication By Example:Using React Router 6 [1]. I am using the following dependencies:

react-router-dom 6.3.0
react 18.2 
auth0-react 2.0.1

Everything works fine until I try to call getAccessTokenSilently() inside useEffect() which causes an infinite loop. I searched all related topics but couldn’t find a solution.

Minimal code snippets for repro (following closely the tutorial above):

Auth0ProviderWithNavigate implementation:

import { Auth0Provider } from '@auth0/auth0-react';
import React, { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';

export const Auth0ProviderWithNavigate = ({ children }) => {
  const navigate = useNavigate();
  const onRedirectCallback = (appState) => {
    navigate(appState?.returnTo || window.location.pathname);
  };

  if (!(domain && clientId && redirectUri)) {
    return null;
  }

  return (
    <Auth0Provider
      domain={domain}
      clientId={clientId}
      authorizationParams={{
        audience: audience,
        redirect_uri: redirectUri
      }}
      onRedirectCallback={onRedirectCallback}
      useRefreshTokens={true}
    >
      {children}
    </Auth0Provider>
  );
};

AuthenticationGuard is included on all routes that require authentication:

import { withAuthenticationRequired } from '@auth0/auth0-react';

export const AuthenticationGuard = ({ component }) => {
  const Component = withAuthenticationRequired(component, {
    onRedirecting: () => (
      <div className="page-layout">
        Loading...
      </div>
    ),
  });

  return <Component />;
};

index.tsx implementation:

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from 'react-router-dom';
import { Auth0ProviderWithNavigate } from './Auth0Provider';

const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(
  <React.Fragment>
    <BrowserRouter>
      <Auth0ProviderWithNavigate>
        <App />
      </Auth0ProviderWithNavigate>
    </BrowserRouter>
  </React.Fragment>
);

reportWebVitals();

App.tsx which I also see to be called infinitely after I check getAccessTokenSilently() in useEffect():

import * as React from 'react';
import { Routes, Route } from 'react-router-dom';
import Home from 'pages/Home';
import { AuthenticationGuard } from 'components/AuthenticationGuard';
import { AppProvider } from './context';

export default function App(): JSX.Element {
  const { isAuthenticated } = useAuth0();
  console.log('isAuthenticated: ', isAuthenticated); // <------------ this prints in infinite loop
  return (
    <React.Fragment>
      <AppProvider>
          <Routes>
            <Route path="/" element={<AuthenticationGuard component={Home} />} />
          </Routes>
        </div>
      </AppProvider>
    </React.Fragment>
  );
}

AppProvider implementation:

import React, { createContext, useReducer } from 'react';

const AppProvider = ({ children }: ProviderProps) => {
  const [state, dispatch] = useReducer(combinedReducers, initialState);
  return <AppContext.Provider value={{ state, dispatch }}>{children}</AppContext.Provider>;
};
export { AppProvider };

Home component implementation where the infinite loop happens:

import * as React from 'react';
import { useEffect } from 'react';

export default function Home(): JSX.Element {
  useEffect(() => {
    (async () => {
      const token = await getAccessTokenSilently({
        authorizationParams: {
          audience: audience
        },
      });
    console.log('token ', token); // <----------- this prints in infinite loop
    })();
  }, []);

  return (
    <div>Hello from app!</div>
  );
}

When I call getAccessTokenSilently to access my own api, I don’t experience any issues. It only happens when trying to use getAccessTokenSilently in useEffect. Any pointers on how to resolve this or ideas about why is this happening will be much appreciated. Many thanks!!

[1] React Authentication By Example: Using React Router 6

2 Likes

Does adding useRefreshTokensFallback={true} to <Auth0Provider /> help?

I ran into a similar issue and this might help you.

Related thread: Auth0 spa 2.x returning missing_refresh_token - #18 by frederik.prijck

The result is still the same after adding useRefreshTokensFallback to <Auth0Provider />

I see the linked post is for auth0-spa-js, however, I am only using auth0-react.

I’ve root caused this issue to be due to the usage of withAuthenticationRequired inside < AuthenticationGuard /> on the route for Home component. However, I don’t understand fully why the withAuthenticationRequired cause the infinite loop.

Hey @dgeo have you found any solution for this problem? I’m stuck with same.

If someone is still stuck with this problem maybe I have a solution - I had infinite loop after i started using withAuthenticationRequired and getAccessTokenSilently in useEffect in child component that renders after authorization.

Adding audience into authorizationParams object for configuring Auth0Provider somehow fixed it.

My Auth0Provider params looking like this now -

<Auth0Provider
      domain={domain}
      clientId={clientId}
      authorizationParams={{
        redirect_uri: window.location.origin,
        audience:  audience,
      }}
    >
        <App />
    </Auth0Provider>