Redirecting to login when refresh token expires breaks normal login

Hi,

I’m making a webapp with a React frontend and .NET backend. Further, I’m using Axios to connect to .NET from React and am using the Auth0 React SDK to work with Auth0. When a user’s login expires, I want the page to redirect to the login screen. By giving my Axios instance the following interceptor, I’m able to do that.

const {getAccessTokenSilently, loginWithRedirect} = useAuth0()  
  
const axiosInstance = axios.create()  
  
axiosInstance.interceptors.request.use(async function (config) {  
    try {  
        const token: string = await getAccessTokenSilently()  
        config.headers.Authorization = `Bearer ${token}`  
        return config  
    } catch (error) {  
        if (typeof error === 'object' && isDefined(error) && 'error' in error && (error.error === 'missing_refresh_token')) {  
            await loginWithRedirect();  
        }  
        return config  
    }  
}, async function (error) {  
    // Do something with request error  
    return await Promise.reject(error)  
})

However, when this interceptor is included in the app, the user will be immediately redirected to the login screen after logging in and reaching my login callback screen, which is the following React component

import {useAuth0} from "@auth0/auth0-react";  
import {Paragraph, Title} from "../styles/text.ts";  
import {Button} from "reactstrap";  
import {Link, useNavigate} from "react-router-dom";  
  
const LoginCallback = () => {  
    const logoutCallback = import.meta.env.VITE_REACT_APP_AUTH0_LOGOUT_CALLBACK_URL  
    const {error, isAuthenticated, isLoading, logout} = useAuth0()  
    const navigate = useNavigate()  
  
  
    if (error) {  
        return (  
            <>  
                <Title>Error</Title>  
                <Paragraph>There's been an error authenticating you! Specifically the following: "{error.message}".  
                    Click the button below to try to login again</Paragraph>  
                <Button onClick={() => navigate("/login")}>Login</Button>  
            </>        )  
    }  
  
    if (isLoading) {  
        return (  
            <Paragraph>Give us a minute as we load your user information!</Paragraph>  
        )  
    }  
  
    if (isAuthenticated) {  
        return (  
            <>  
                <Title>You're authenticated!</Title>  
                <Paragraph>You're ready to continue! Click <Link to={'/'}>here</Link> to go to the  
                    homepage</Paragraph>  
            </>        )  
    }  
  
    return (  
        <>  
            <Title>Unexpected error</Title>  
            <Paragraph>For some reason, you are authenticated, but we can't get that information. Please contact  
                support. To try again, hit the logout button below and try to login again</Paragraph>  
            <Button onClick={() => logout({logoutParams: {returnTo: logoutCallback}})}>Logout</Button>  
        </>    )  
}  
  
export default LoginCallback

From my debugging, it seems that the queries that are called on the login callback screen (from other parent components and contexts) are calling getAccessTokenSilently in that interceptor and getting a missing_refresh_token error, even though the user has just logged in. I’m fairly certain that this is the issue, as login does work correctly when the following lines that cause the redirect are removed:

if (typeof error === 'object' && isDefined(error) && 'error' in error && (error.error === 'missing_refresh_token')) {  
    await loginWithRedirect();  
}

I can confirm that, when these lines are taken out, about 2-4 missing_refresh_token errors happen before queries start getting the token and consequentially the data they are requesting. After those 2-4 errors, the app works fine with no issues. This error happens on both my development and production tenant. I’m running version 2.2.4 of the @auth0/auth0-react package, am using a basic Vite React app, and have the following configuration for my Auth0 provider

const domain = import.meta.env.VITE_REACT_APP_AUTH0_DOMAIN;  
const clientId = import.meta.env.VITE_REACT_APP_AUTH0_CLIENT_ID;  
const redirectUri = import.meta.env.VITE_REACT_APP_AUTH0_LOGIN_CALLBACK_URL;  
const audience = import.meta.env.VITE_REACT_APP_AUTH0_AUDIENCE;

<Auth0Provider  
    domain={domain}  
    clientId={clientId}  
    authorizationParams={{  
        audience: audience,  
        redirect_uri: redirectUri,  
    }}  
    useRefreshTokens={true}  
    cacheLocation={"localstorage"}  
>
...
</Auth0Provider>

I am also getting a missing_refresh_token error on the getTokenSilently() call, immediately after the user logs in on a loginWithRedirect() call (after calling handleRedirectCallback()).

I’m using auth0-spa-js, which I believe is that powers the Auth0 React SDK under the hood.