handleRedirectCallback failing with "Invalid State" error & empty response

I am using the @auth0/auth0-spa-js module in my reactjs application.

I am using loginWithRedirect and as per the doc, I have to call handleRedirectCallback after we are redirected from Auth0 back to SPA.

So, in App component, I have used an useEffect listening to the query params. If code query param is present in the URL, then I am calling handleRedirectCallback.

Code:

import createAuth0Client from "@auth0/auth0-spa-js";
import { useEffect, useState } from "react";
import { isEmpty } from "lodash";
import { BrowserRouter, useSearchParams } from "react-router-dom";

function LoginButton({ auth0, setUser }) {
  return (
    <>
      <button
        onClick={async () => {
          await auth0.loginWithRedirect({
            redirect_uri: "http://localhost:3000/",
          });
          // await auth0.loginWithPopup();
          const _user = await auth0.getUser();
          setUser(_user);
        }}
      >
        LOGIN
      </button>
    </>
  );
}

function App({ auth0, user, setUser }) {
  const [searchParams] = useSearchParams();

  useEffect(() => {
    (async () => {
      if (searchParams && searchParams.get("code")) {
        let code = searchParams.get("code");
        console.log("App -> code", code);
        let res = await auth0.handleRedirectCallback();
        console.log("App -> handleRedirectCallback -> res", res);
      }
    })();
  }, [auth0, searchParams]);

  return (
    <>
      <h1>APP</h1>
      <hr />
      {isEmpty(user) && <LoginButton auth0={auth0} setUser={setUser} />}
      {!isEmpty(user) && (
        <>
          <Profile auth0={auth0} user={user} />
        </>
      )}
      <LogoutButton auth0={auth0} setUser={setUser} />
    </>
  );
}

function AppWrapper() {
  const [auth0, setAuth0] = useState();
  const [user, setUser] = useState();

  useEffect(() => {
    (async () => {
      const _auth0 = await createAuth0Client({
        domain: "DOMAIN,
        client_id: "CLIENT-ID",
        cacheLocation: "localstorage",
        useRefreshTokens: true,
      });
      setAuth0(_auth0);
      const _user = await _auth0.getUser();
      console.log("AppWrapper -> _user", _user);
      setUser(_user);
    })();
  }, []);

  if (!auth0) {
    return (
      <>
        <p>Loading...</p>
      </>
    );
  }

  return (
    <>
      <BrowserRouter>
        <App auth0={auth0} user={user} setUser={setUser} />
      </BrowserRouter>
    </>
  );
}

export default AppWrapper;

I am getting the following error in the console along with an empty response in appState:

App → code xxxxxxxxxxxx

Auth0Client.ts:668 Uncaught (in promise) Error: Invalid state
at e. (Auth0Client.ts:668:1)
at tslib.es6.js:102:1
at Object.next (tslib.es6.js:83:1)
at tslib.es6.js:76:1
at new Promise ()
at o (tslib.es6.js:72:1)
at e.handleRedirectCallback (Auth0Client.ts:660:1)
at App.js:75:1
at App.js:78:1
at commitHookEffectListMount (react-dom.development.js:23150:1)

App → handleRedirectCallback → res {appState: undefined}

Did you ever resolve this? I am running into the same issue, but with NextJS.

I don’t know why you’re running into this issue specifically, but I can give you the information necessary to troubleshoot it.

If we go inspect the source code for loginWithRedirect and handleRedirectCallback we can observe that it internally uses a Transaction Manager and a helper function to store a session storage object with some random values. In the latter method it then checks these values to ensure they are present/valid.

If you look at all of the places in the source code where you get that “Invalid State” error you can see what conditions trigger it auth0-spa-js/src/Auth0Client.ts at f2e566849efa398ca599daf9ebdfbbd62fcb1894 · auth0/auth0-spa-js · GitHub

You can also use the browser dev tools. Go to Application tab > Session Storage and find a key that starts with a0.spajs.txs.

Hi everyone and @SreekarMouli98!

I am sorry about the delayed response to your inquiry!

As @TheMuffinMan has mentioned, this indeed appears to be an issue with the transactionManager which might be deleting the state cookie before the token exchange is completed, resulting in an Invalid State error.

I would highly recommend to review this community post regarding the matter where the solution is explained in high details:

If there are any other questions, feel free to leave a reply!

Kind Regards,
Nik

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.