App infinitely redirecting after login

I’ve followed your recommendation by

  • adjusting the <Auth0Provider .../> to include useRefreshTokens={true} and cacheLocation="localstorage"
  • ensured that any scopes are also passed into the Auth0Provider (yes we do use getAccessTokenSilently)
  • we do actually use a custom domain

But it still seems to be stuck in an infinite redirect loop.

I’ve actually managed to isolate the issue into a new react app. (made with create-react-app)

index.js:

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import './index.css';
import { Auth0Provider } from "@auth0/auth0-react";
import config from './config.json';

const onRedirectCallback = (appState) => {
	window.history.replaceState({}, document.title, appState && appState.targetUrl ? appState.targetUrl : window.location.pathname);
};

ReactDOM.render(
  <Auth0Provider
  	connection={config.connection}
    domain={config.domain}
    clientId={config.clientId}
	auddience={config.audience}
    redirectUri={window.location.origin}
	onRedirectCallback={onRedirectCallback}
	useRefreshTokens={true}
	cacheLocation="localstorage"
  >
    <App />
  </Auth0Provider>,
  document.getElementById("root")
);

App.js

import logo from "./logo.svg";
import "./App.css";
import { useAuth0 } from "@auth0/auth0-react";
import { useEffect } from "react";
import config from './config.json';

const App = () => {

	const { isAuthenticated, isLoading, loginWithRedirect, logout, getAccessTokenSilently } = useAuth0();

	useEffect(() => {

		if(isLoading){
			console.log('app is loading');
			return;
		}

		if(!isAuthenticated){
			console.log('not authenticated. redirecting to login');
			loginWithRedirect();
			return;
		}

		//this causes an infinite loop:
		//getToken(config.customApi);

		//this causes an infinite loop:
		//getToken(config.managementApi);

		//this works fine
		getToken({});

	}, [isLoading, isAuthenticated]);

	const getToken = (options) => {
		console.log(`retrieving token for '${options.audience}'`);
		getAccessTokenSilently(options).then(token => {
			console.log('retrieved token!', token);
		})
		.catch(e => {
			console.error('failed to get token!', e);
		});
	};

	if(isLoading){
		return (<div>loading</div>);
	}

	if(!isAuthenticated){
		return (<div>you're not authenticated!</div>);
	}

	const handleLogoutClick = (e) => {
		e.preventDefault();
		logout();
	}

	const render = () => {
		return (
			<div className="App">
				<header className="App-header">
					<img src={logo} className="App-logo" alt="logo" />
					<p>
						Edit <code>src/App.js</code> and save to reload.
					</p>
					<button onClick={handleLogoutClick}>Log out</button>
				</header>
			</div>
		);
	};

	return render();
};

export default App;

config.json:

{
	"connection": "app",
    "domain": "ts-app-dev.au.auth0.com",
    "clientId": "(my client id)",
	"audience": "https://domain.com/api/v2/",
	"customApi": {
		"audience": "https://api.identifier"
	},
	"managementApi": {
		"audience": "https://domain/api/v2/"
	}
}

And the only package.json deps you need are:

    "@auth0/auth0-react": "^1.5.0",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-scripts": "4.0.3"
  },

Above - if you uncomment the lines App.js, you’ll get an infinite loop.
It seems that if you provide the audience option to getTokenSilently({ audience: ... ), while in “incognito mode” you get stuck in an infinite loop.

Note: in auth0 management interface, i have

  • a react app
  • the auth0 management api (i dont use this except for allowing users to reset their password)
  • a custom api (which contains all of my app’s functionality)
    So i have 2 audiences (one for custom api, one for management api)

Any suggestions?
I can send you guys the fully zipped project + a log in for my app if you like.

1 Like