I am using Auth0 as my authentication provider for a SPA using React. I have followed the Auth0 react tutorial and this more detailed tutorial from their blog.
I am currently just using just email/password authentication. And the authentication works as expected for login/logout, retrieving user info etc.
However, when I refresh the page, the isAuthenticated
value from the useAuth0
always returns false. Even after isLoading
resolves to true, hence I have to log in again.
This behaviour strangely does not occur on Chrome or Firefox. It fails on Brave and Safari.
I noticed in a forum post on Auth0 (another person with a similar problem) that the Auth0Provider
should be doing a authorize
call using prompte=none
, and it is. It also returns a successful 202
shortly after the page loads (but doesn't change isAuthenticated
to true
). This call also sets a cookie auth0.is.authenticated=true
.
authorize?client_id=VALUE&redirect_uri=VALUE&scope=openid%20profile%20email&response_type=code&response_mode=web_message&state=VALUE&nonce=VALUE&code_challenge=VALUE&code_challenge_method=S256&prompt=none&auth0Client=VALUE
Here is my route that checks the auth state. This component is wrapped in the Auth0ProviderWithHistory
code as suggested in the Auth0 tutorials.
export default function Routes() {
const { isLoading, isAuthenticated } = useAuth0()
const getDashboard = () => {
//determine which dashboard to return
}
if (isLoading) return <p>Loading...</p>
if (isAuthenticated) {
return (
<Suspense fallback={<p>loading...</p>}>
<Switch>
<Route exact path="/">
{getDashboard()}
</Route>
<Route path="/customer/:customerId">
<Customer />
</Route>
<Route>
<NotFound />
</Route>
</Switch>
</Suspense>
)
}
return <SignInAndRegister />
}
I have noticed when I reload the page, and call the loginWithRedirect
function I am not redirected to the Universal Login page, instead there are two token calls (POST and OPTIONS). The POST call response has the following details, should I somehow capture this and saving them to reuse them to login?
access_token: "VALUE"
expires_in: 86400
id_token: "VALUE"
scope: "openid profile email"
token_type: "Bearer"
As an experiment, I downloaded the react sample on the "Quick Start" section of an application in the Auth0 dashboard to see if the behaviour was replicated there. And it was.
I had the impression that the Auth0Provider
should be handling the silent authentication automagically, is this not the case?
There are not many options to use with auth0-react
npm package, so I am not sure what to try next. The only available functions are:
getAccessTokenSilently: ƒ (opts)
getAccessTokenWithPopup: ƒ (opts)
getIdTokenClaims: ƒ (opts)
isAuthenticated: false
isLoading: true
loginWithPopup: ƒ (opts)
loginWithRedirect: ƒ (opts)
If this isn't possible, it looks like I might have to migrate to the @auth0/auth0-spa-js
SDK.
The issue was that Brave and Safari both use Intelligent Tracking Prevention (ITP), which was preventing the silent authentication from working.
The solution that worked for me was to enable rotating refresh tokens (via the Auth0 dashboard) and providing additional props to the Auth0 provider.
The two new props to add are: useRefreshTokens={true}
and cacheLocation="localstorage"
.
<Auth0Provider
domain={process.env.REACT_APP_AUTH0_DOMAIN}
clientId={process.env.REACT_APP_AUTH0_CLIENT_ID}
redirectUri={window.location.origin}
onRedirectCallback={onRedirectCallback}
useRefreshTokens={true}
cacheLocation="localstorage"
>
{children}
</Auth0Provider>
Here are the official docs to learn more about rotating refresh tokens: https://auth0.com/docs/tokens/refresh-tokens