19

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.

Charklewis
  • 4,427
  • 4
  • 31
  • 69
  • Well, you will have to verify on every reload if the user is authenticated already and then let the user go to that same route otherwise sign him out. I hope you are saving some auth related info in cookies or local storage. – Sheelpriy Aug 22 '20 at 15:37
  • Have you checked your auth0 configuration? it seems your configuration is not right. – Sheelpriy Aug 22 '20 at 17:47
  • Is there a specific configuration to check? The app works to login etc so I know the `domain`, `clientId`, Callback URL, Logout URL and Web Origins are correct as the login/logout normal flows break if they are wrong. – Charklewis Aug 22 '20 at 18:06
  • hi @Charlewis I guess this is an open issue. ref: https://github.com/auth0-samples/auth0-react-samples/issues/192 – Sheelpriy Aug 22 '20 at 18:18
  • @Sheelpriy this issue is unrelated to my problem. I have added more info to the question. – Charklewis Aug 22 '20 at 20:33
  • Could you see if one of these is related to your issue? https://github.com/auth0/auth0-react/issues/100 OR https://github.com/auth0/auth0-react/issues/82 OR https://github.com/auth0/auth0-react/issues/93. I am having a similar issue with auth0, is it related? https://stackoverflow.com/questions/63465924/samesite-cookie-error-on-localhost-with-auth0 – Kenny John Jacob Aug 26 '20 at 14:30
  • 1
    Those issues are slightly different from what I am experiencing, I have created an issue on the repo - https://github.com/auth0/auth0-react/issues/101 – Charklewis Aug 27 '20 at 08:07

1 Answers1

33

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

Charklewis
  • 4,427
  • 4
  • 31
  • 69
  • 1
    Yep, this fixed my issue too. For anyone else stumbling upon this, here is the github issue for this https://github.com/auth0/auth0-react/issues/101 – Kenny John Jacob Aug 28 '20 at 05:15
  • 2
    With the growth of anti-tracking features by browsers, you'll find that legitimate uses (such as the cookies created by Auth0) are stripped because they could appear to be tracking cookies. Rotating refresh tokens circumvent this issue by storing the refresh token within local storage, or in memory which is not subject to the controls implemented by ITP. – Tim Ferrell Aug 28 '20 at 13:26
  • 1
    worth noting this also solves the similar issue in Nextjs's static site generation where auth state does not persist after page change. – KuN Feb 10 '21 at 07:00
  • Thanks this was driving me insane for some time until I found this. – Vijay Prema Jul 29 '22 at 08:13
  • For me, simply adding the `cacheLocation: 'localstorage'` (to JS, in my case) param fixed it - no further steps. – Mitya Apr 28 '23 at 13:53