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>