Ionic & Capacitor (React) Quickstart Works in Web but isAuthenticated Does Not Update in Mobile App

Hi everyone,

I’m testing the official Auth0 React quickstart with Ionic & Capacitor. I didn’t make any changes—just downloaded the code and ran it on both web and Android.

  • Web: Everything works perfectly. isAuthenticated and user Update as expected after login.

  • Mobile (Android/iOS): After logging in, isAuthenticated remains false and user doesn’t update at all.

Here’s the relevant code (official GitHub quickstart, I only added a logout button for testing):

// @ts-nocheck
import {
  IonContent,
  IonHeader,
  IonPage,
  IonTitle,
  IonToolbar,
} from "@ionic/react";

import { useAuth0 } from "@auth0/auth0-react";
import "./Home.css";
import LoginButton from "../components/LoginButton";
import LogoutButton from "../components/LogoutButton";
import Profile from "../components/Profile";

const Home: React.FC = () => {
  const { isLoading, isAuthenticated, user } = useAuth0();
  console.log(isLoading, user);

  if (isLoading) {
    return <div>Loading..... </div>;
  }

  return (
    <IonPage>
      <IonHeader>
        <IonToolbar>
          <IonTitle>Auth0 React Sample</IonTitle>
        </IonToolbar>
      </IonHeader>
      <IonContent fullscreen>
        <IonHeader collapse="condense">
          <IonToolbar>
            <IonTitle size="large">Auth0 React Sample</IonTitle>
          </IonToolbar>
        </IonHeader>
        <div className="container">
          <span>{"is authenticated:" + isAuthenticated}</span>
          <Profile />
          <>
            <LogoutButton />
            <LoginButton />
          </>
        </div>
      </IonContent>
    </IonPage>
  );
};

export default Home;

I suspect this might be related to the difference in how Auth0 handles web vs native mobile login flows.

Has anyone successfully used the Auth0 React quickstart with Ionic & Capacitor on mobile? How do you ensure isAuthenticated and user Update correctly on native apps?

Any guidance would be greatly appreciated!


(post deleted by author)




// @ts-nocheck
import { Redirect, Route } from "react-router-dom";
import { IonApp, IonRouterOutlet, setupIonicReact } from "@ionic/react";
import { IonReactRouter } from "@ionic/react-router";
import { App as CapApp } from "@capacitor/app";
import { Browser } from "@capacitor/browser";
import { useAuth0 } from "@auth0/auth0-react";
import { callbackUri } from "./auth.config";
import Home from "./pages/Home";

/* Core CSS required for Ionic components to work properly */
import "@ionic/react/css/core.css";

/* Basic CSS for apps built with Ionic */
import "@ionic/react/css/normalize.css";
import "@ionic/react/css/structure.css";
import "@ionic/react/css/typography.css";

/* Optional CSS utils that can be commented out */
import "@ionic/react/css/padding.css";
import "@ionic/react/css/float-elements.css";
import "@ionic/react/css/text-alignment.css";
import "@ionic/react/css/text-transformation.css";
import "@ionic/react/css/flex-utils.css";
import "@ionic/react/css/display.css";

/* Theme variables */
import "./theme/variables.css";
import { useEffect, useState } from "react";

import { Capacitor } from "@capacitor/core";

setupIonicReact({
  mode: "md",
});

const App: React.FC = () => {
  const { handleRedirectCallback } = useAuth0();
  const [redirectHandled, setRedirectHandled] = useState(false);
  const isNative = Capacitor.isNativePlatform();
  const [testOne, setTestOne] = useState("test one initial");

  useEffect(() => {
    CapApp.addListener("appUrlOpen", async ({ url }) => {
      console.log("appUrlOpen event received: " + url);
      setTestOne("test one executed");

      if (url.startsWith(callbackUri)) {
        if (
          url.includes("state") &&
          (url.includes("code") || url.includes("error"))
        ) {
          await handleRedirectCallback(url);
        }
        await Browser.close();
        setRedirectHandled(true); // mark redirect done
      }
    });
  }, [handleRedirectCallback]);

  if (isNative && !redirectHandled) {
    return <div> {testOne}</div>;
  }

  return (
    <IonApp>
      <IonReactRouter>
        <IonRouterOutlet>
          <Route exact path="/home">
            <Home />
          </Route>
          <Route exact path="/">
            <Redirect to="/home" />
          </Route>
        </IonRouterOutlet>
      </IonReactRouter>
    </IonApp>
  );
};

export default App;