> ## Documentation Index
> Fetch the complete documentation index at: https://docs-staging-actions-triggers-prototype.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Ajouter la connexion à votre application Ionic React avec l’application Capacitor

> Ce guide explique comment intégrer Auth0 avec une application Ionic (React) & Capacitor en utilisant la trousse SDK React Auth0.

export const AuthCodeGroup = ({children, dropdown}) => {
  const [processedChildren, setProcessedChildren] = useState(children);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      unsubscribe = window.autorun(() => {
        const processChildren = node => {
          if (typeof node === "string") {
            let processedNode = node;
            for (const [key, value] of window.rootStore.variableStore.values.entries()) {
              const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
              processedNode = processedNode.replaceAll(new RegExp(escapedKey, "g"), value);
            }
            return processedNode;
          } else if (Array.isArray(node)) {
            return node.map(processChildren);
          } else if (node && node.props && node.props.children) {
            return {
              ...node,
              props: {
                ...node.props,
                children: processChildren(node.props.children)
              }
            };
          }
          return node;
        };
        setProcessedChildren(processChildren(children));
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  return <CodeGroup dropdown={dropdown}>{processedChildren}</CodeGroup>;
};

export const QuickstartButtons = ({githubLink, lang = "en"}) => {
  const translations = {
    en: {
      viewOnGithub: "View On GitHub",
      loginAndDownload: "Download Sample"
    },
    "fr-ca": {
      viewOnGithub: "Afficher sur GitHub",
      loginAndDownload: "Télécharger un exemple"
    },
    "ja-jp": {
      viewOnGithub: "Githubで表示",
      loginAndDownload: "サンプルをダウンロード"
    }
  };
  const text = translations[lang] || translations.en;
  const parseGithubUrl = url => {
    try {
      const urlObj = new URL(url);
      const pathParts = urlObj.pathname.split("/").filter(Boolean);
      if (pathParts.length >= 4 && pathParts[2] === "tree") {
        const repoName = pathParts[1];
        const branch = pathParts[3];
        const path = pathParts.slice(4).join("/") || undefined;
        return {
          repo: repoName,
          branch,
          path
        };
      }
      console.warn("Could not parse GitHub URL:", url);
      return null;
    } catch (error) {
      console.error("Error parsing GitHub URL:", error);
      return null;
    }
  };
  const handleDownload = async () => {
    const params = parseGithubUrl(githubLink);
    if (!params) {
      console.error("Invalid GitHub URL format");
      return;
    }
    try {
      await window.Auth0DocsUI?.getSample(params);
    } catch (error) {
      console.error("Failed to download sample:", error);
    }
  };
  return <div className="quickstart_buttons flex flex-wrap gap-3 mb-4">
      <a href={githubLink} target="_blank" rel="noopener noreferrer" className="no_external_icon quickstart_button inline-flex items-center justify-center px-6 py-3 text-sm font-medium rounded-[18px] bg-black dark:bg-white !text-white dark:!text-black hover:bg-gray-800 dark:hover:bg-gray-100 transition-colors">
        {text.viewOnGithub}
      </a>
      <button onClick={handleDownload} type="button" className="no_external_icon quickstart_button inline-flex items-center justify-center px-6 py-3 text-sm font-medium rounded-[18px] border border-gray-300 dark:border-[#454545] bg-white dark:bg-[#272728] !text-black dark:!text-white hover:bg-gray-50 dark:hover:bg-neutral-800 transition-colors">
        {text.loginAndDownload}
      </button>
    </div>;
};

export const LoggedInForm = ({sampleApp}) => {
  const LS_APPS_KEY = "auth_demo_apps";
  const LS_APP_CFG_KEY = "auth_demo_app_cfg";
  const CHANNEL = "auth_flows_sync_v1";
  const mkChannel = () => new BroadcastChannel(CHANNEL);
  function uid() {
    return Math.random().toString(36).slice(2) + Date.now().toString(36);
  }
  function loadApps() {
    const raw = localStorage.getItem(LS_APPS_KEY);
    if (raw) return JSON.parse(raw);
    const seeded = [{
      id: "{yourClientId}",
      name: "Default App"
    }];
    localStorage.setItem(LS_APPS_KEY, JSON.stringify(seeded));
    return seeded;
  }
  function saveApps(apps) {
    localStorage.setItem(LS_APPS_KEY, JSON.stringify(apps));
  }
  function loadCfg() {
    const raw = localStorage.getItem(LS_APP_CFG_KEY);
    return raw ? JSON.parse(raw) : {};
  }
  function saveCfg(cfg) {
    localStorage.setItem(LS_APP_CFG_KEY, JSON.stringify(cfg));
  }
  const RightChevron = ({className = "w-5 h-5", ...props}) => <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke="currentColor" fill="none" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className} {...props}>
      <polyline points="9 18 15 12 9 6" />
    </svg>;
  const LightningIcon = () => <svg width="24" height="24" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
      <path fillRule="evenodd" clipRule="evenodd" className="fill-[#3F59E4] dark:fill-[#99A7F1]" d="M24.971 30.152H7.088c-1.786 0-2.745-2.103-1.574-3.453l19.07-21.988c1.33-1.532 3.835-.4 3.569 1.607L24.97 30.152z" />
      <path fillRule="evenodd" clipRule="evenodd" className="fill-[#3F59E4] dark:fill-[#99A7F1]" d="M23.201 17.885h17.885c1.787 0 2.746 2.102 1.575 3.453l-19.073 21.99c-1.33 1.532-3.835.4-3.568-1.607L23.2 17.885z" />
    </svg>;
  const LayersIcon = () => <svg width="24" height="24" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
      <path className="fill-[#3F59E4] dark:fill-[#99A7F1]" d="M34.54 29.135l6.373 3.183c1.566.782 1.566 3.017 0 3.8l-14.815 7.396a4.623 4.623 0 01-4.125 0L7.174 36.12c-1.565-.782-1.565-3.017 0-3.798l6.532-3.214" />
      <path className="fill-[#AAB6F3] dark:fill-[#3449BA]" d="M34.54 18.86l6.373 3.183c1.566.782 1.566 3.016 0 3.8L26.098 33.24a4.623 4.623 0 01-4.125 0L7.174 25.843c-1.565-.781-1.565-3.016 0-3.798l6.33-3.164" />
      <path className="fill-[#CFD6F8] dark:fill-[#22307C]" d="M21.94 23.058L7.306 15.745c-1.62-.81-1.62-3.123 0-3.932l14.631-7.319a4.693 4.693 0 014.194 0l14.648 7.319c1.622.81 1.62 3.124 0 3.932L26.13 23.058c-1.321.66-2.873.66-4.191 0z" />
    </svg>;
  const GithubIcon = () => <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="w-5 h-5">
      <path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path>
    </svg>;
  function IconTile({children}) {
    return <div className="
          shrink-0 grid place-items-center w-10 h-10 rounded-lg
          bg-indigo-50 ring-1 ring-indigo-200/60
          dark:bg-indigo-950/40 dark:ring-white/10
        ">
        {children}
      </div>;
  }
  function Card({className = "", children}) {
    return <div className={`rounded-2xl shadow-sm ring-1 ring-zinc-200 dark:ring-zinc-800 ${className}`}>{children}</div>;
  }
  function Button({variant = "primary", type = "button", onClick, children}) {
    const base = "inline-flex items-center justify-center gap-2 h-10 px-4 rounded-xl font-medium transition";
    let styles = "";
    if (variant === "primary") {
      styles = "mint-bg-indigo-600 text-white hover:mint-bg-indigo-700";
    } else if (variant === "outline") {
      styles = "border border-zinc-300 dark:border-zinc-700 mint-bg-transparent hover:mint-bg-zinc-50 dark:hover:mint-bg-zinc-800";
    } else if (variant === "ghost") {
      styles = "hover:mint-bg-zinc-100 dark:hover:mint-bg-zinc-800";
    }
    return <button type={type} onClick={onClick} className={`${base} ${styles}`}>
        {children}
      </button>;
  }
  function Input({id, label, value, onChange, placeholder, name}) {
    return <label className="block space-y-1">
        <span className="text-sm text-zinc-700 dark:text-zinc-300">{label}</span>
        <input id={id} name={name} className="w-full h-11 px-3 rounded-xl border border-zinc-300 dark:border-zinc-700 bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-indigo-500" placeholder={placeholder} value={value} onChange={e => onChange(e.target.value)} />
      </label>;
  }
  function Select({label, value, onChange, options}) {
    return <label className="block space-y-1 max-w-[300px]">
        <span className="text-sm text-zinc-700 dark:text-zinc-300">{label}</span>
        <div className="relative">
          <select className="w-full h-11 appearance-none px-3 pr-9 rounded-xl border border-zinc-300 dark:border-zinc-700 bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-indigo-500" value={value} onChange={e => onChange(e.target.value)}>
            <optgroup label="Generic Applications">
              {options.map(o => <option key={o.id} value={o.id}>
                  {o.name}
                </option>)}
            </optgroup>
          </select>
          <svg className="pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 w-5 h-5 text-zinc-500" viewBox="0 0 24 24">
            <path d="M7 10l5 5 5-5z" fill="currentColor" />
          </svg>
        </div>
      </label>;
  }
  function Toast({open, onClose, children}) {
    useEffect(() => {
      if (!open) return;
      const t = setTimeout(onClose, 2200);
      return () => clearTimeout(t);
    }, [open, onClose]);
    return <div className={`fixed right-4 top-4 z-50 transition ${open ? "opacity-100 translate-y-0" : "opacity-0 -translate-y-2 pointer-events-none"}`}>
        <div className="flex items-center gap-2 rounded-xl shadow ring-1 ring-emerald-200 bg-white dark:bg-zinc-900 px-4 py-2">
          <span className="w-1.5 h-8 rounded-l bg-emerald-500" />
          <svg className="w-5 h-5 text-emerald-600" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
            <path d="M20 6L9 17l-5-5" />
          </svg>
          <span className="text-sm text-zinc-900 dark:text-zinc-100">{children}</span>
        </div>
      </div>;
  }
  function Flows() {
    const [route, setRoute] = useState("menu");
    const [apps, setApps] = useState(loadApps());
    const [cfg, setCfg] = useState(loadCfg());
    const [selected, setSelected] = useState(apps[0]?.id || "");
    const [toast, setToast] = useState(false);
    const [bc] = useState(() => mkChannel());
    useEffect(() => {
      if (!apps.find(a => a.id === selected)) {
        setSelected(apps[0]?.id || "");
      }
    }, [apps, selected]);
    useEffect(() => {
      const onMsg = e => {
        const {type, payload} = e.data || ({});
        switch (type) {
          case "NAV":
            setRoute(payload.route);
            break;
          case "SELECT":
            setSelected(payload.appId);
            break;
          case "APPS_UPDATED":
            setApps(loadApps());
            break;
          case "CFG_UPDATED":
            setCfg(loadCfg());
            setToast(true);
            break;
          default:
            break;
        }
      };
      bc.addEventListener("message", onMsg);
      return () => bc.removeEventListener("message", onMsg);
    }, [bc]);
    const nav = nextRoute => {
      setRoute(nextRoute);
      bc.postMessage({
        type: "NAV",
        payload: {
          route: nextRoute
        }
      });
    };
    const selectApp = appId => {
      setSelected(appId);
      bc.postMessage({
        type: "SELECT",
        payload: {
          appId
        }
      });
    };
    const onCreate = name => {
      const id = uid();
      const next = [...apps, {
        id,
        name: name || "Untitled"
      }];
      setApps(next);
      saveApps(next);
      bc.postMessage({
        type: "APPS_UPDATED"
      });
      selectApp(id);
      nav("integrate");
    };
    const onSaveCfg = (appId, data) => {
      const next = {
        ...cfg,
        [appId]: data
      };
      setCfg(next);
      saveCfg(next);
      setToast(true);
      bc.postMessage({
        type: "CFG_UPDATED"
      });
    };
    return <div>
        {route === "menu" && <Menu onCreate={() => nav("create")} onIntegrate={() => nav("integrate")} />}

        {route === "create" && <CreateForm onCancel={() => nav("menu")} onSave={onCreate} />}

        {route === "integrate" && <IntegrateForm apps={apps} selected={selected} onSelect={selectApp} saved={cfg[selected]} onSave={data => onSaveCfg(selected, data)} onCancel={() => nav("menu")} />}

        <Toast open={toast} onClose={() => setToast(false)}>
          Successfully saved your changes.
        </Toast>
      </div>;
  }
  function Menu({onCreate, onIntegrate}) {
    return <ul className="space-y-4 list-none login_list">
        <li className="list-none !px-0">
          <button onClick={onCreate} className="w-full text-left">
            <Card className="p-5 hover:shadow-md transition">
              <div className="flex items-center justify-between">
                <div className="flex items-center gap-4">
                  <IconTile>
                    <LightningIcon />
                  </IconTile>
                  <h2 className="text-lg">Create a new application</h2>
                </div>
                <RightChevron className="w-4 h-4 text-zinc-500" />
              </div>
            </Card>
          </button>
        </li>
        <li className="list-none !px-0">
          <button onClick={onIntegrate} className="w-full text-left">
            <Card className="p-5 hover:shadow-md transition">
              <div className="flex items-center justify-between">
                <div className="flex items-center gap-4">
                  <IconTile>
                    <LayersIcon />
                  </IconTile>
                  <h2 className="text-lg">Integrate with an existing application</h2>
                </div>
                <RightChevron className="w-4 h-4 text-zinc-500" />
              </div>
            </Card>
          </button>
        </li>
        <li className="list-none !px-0">
          <a className="no_external_icon block" href={sampleApp ? sampleApp : "/"} target="_blank" rel="noreferrer">
            <Card className="p-5 hover:shadow-md transition">
              <div className="flex items-center justify-between">
                <div className="flex items-center gap-4">
                  <IconTile>
                    <GithubIcon />
                  </IconTile>
                  <h2 className="text-lg">View a sample application</h2>
                </div>
                <RightChevron className="w-4 h-4 text-zinc-500" />
              </div>
            </Card>
          </a>
        </li>
      </ul>;
  }
  function CreateForm({onSave, onCancel}) {
    const [name, setName] = useState("");
    return <div className="space-y-6">
        <Input id="app-name" label="Application Name" placeholder="My App" value={name} onChange={setName} />
        <p className="text-sm text-zinc-500">You can change this later in the application settings.</p>
        <div className="flex gap-3">
          <Button onClick={() => onSave(name)}>Save</Button>
          <Button variant="outline" onClick={onCancel}>
            Cancel
          </Button>
        </div>
      </div>;
  }
  function IntegrateForm({apps, selected, onSelect, saved, onSave, onCancel}) {
    const [callbacks, setCallbacks] = useState(saved?.callbacks ?? "");
    const [logouts, setLogouts] = useState(saved?.logouts ?? "");
    const [origins, setOrigins] = useState(saved?.origins ?? "");
    useEffect(() => {
      setCallbacks(loadCfg()[selected]?.callbacks ?? "");
      setLogouts(loadCfg()[selected]?.logouts ?? "");
      setOrigins(loadCfg()[selected]?.origins ?? "");
    }, [selected]);
    return <div className="space-y-6">
        <div>
          <span className="block text-sm text-zinc-600 dark:text-zinc-300 mb-1">Select your Application</span>
          <Select label="" value={selected} onChange={onSelect} options={apps} />
        </div>

        <form className="space-y-4" onSubmit={e => {
      e.preventDefault();
      onSave({
        callbacks,
        logouts,
        origins
      });
    }}>
          <Input id="callbacks" name="callbacks" label="Callback URLs" placeholder="http://localhost:3000" value={callbacks} onChange={setCallbacks} />
          <Input id="logout" name="allowed_logout_urls" label="Logout URLs" placeholder="http://localhost:3000" value={logouts} onChange={setLogouts} />
          <Input id="origins" name="web_origins" label="Allowed Web Origins" placeholder="http://localhost:3000" value={origins} onChange={setOrigins} />

          <div className="flex gap-3 pt-2">
            <Button type="submit">Save</Button>
            <Button variant="outline" type="button" onClick={onCancel}>
              Cancel
            </Button>
          </div>
        </form>
      </div>;
  }
  return <div className="w-full mx-auto py-8">
      <Flows />
    </div>;
};

export const SignUpForm = () => {
  const [isAuthenticated, setIsAuthenticated] = useState(false);
  const [storeReady, setStoreReady] = useState(false);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      setStoreReady(true);
      unsubscribe = window.autorun(() => {
        const authenticated = window.rootStore?.sessionStore?.isAuthenticated || false;
        setIsAuthenticated(authenticated);
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, []);
  function LoggedInForm({sampleApp}) {
    const LS_APPS_KEY = "auth_demo_apps";
    const LS_APP_CFG_KEY = "auth_demo_app_cfg";
    const CHANNEL = "auth_flows_sync_v1";
    const mkChannel = () => new BroadcastChannel(CHANNEL);
    function uid() {
      return Math.random().toString(36).slice(2) + Date.now().toString(36);
    }
    function loadApps() {
      const raw = localStorage.getItem(LS_APPS_KEY);
      if (raw) return JSON.parse(raw);
      const seeded = [{
        id: "{yourClientId}",
        name: "Default App"
      }];
      localStorage.setItem(LS_APPS_KEY, JSON.stringify(seeded));
      return seeded;
    }
    function saveApps(apps) {
      localStorage.setItem(LS_APPS_KEY, JSON.stringify(apps));
    }
    function loadCfg() {
      const raw = localStorage.getItem(LS_APP_CFG_KEY);
      return raw ? JSON.parse(raw) : {};
    }
    function saveCfg(cfg) {
      localStorage.setItem(LS_APP_CFG_KEY, JSON.stringify(cfg));
    }
    const RightChevron = ({className = "w-5 h-5", ...props}) => <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke="currentColor" fill="none" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className} {...props}>
        <polyline points="9 18 15 12 9 6" />
      </svg>;
    const LightningIcon = () => <svg width="24" height="24" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
        <path fillRule="evenodd" clipRule="evenodd" className="fill-[#3F59E4] dark:fill-[#99A7F1]" d="M24.971 30.152H7.088c-1.786 0-2.745-2.103-1.574-3.453l19.07-21.988c1.33-1.532 3.835-.4 3.569 1.607L24.97 30.152z" />
        <path fillRule="evenodd" clipRule="evenodd" className="fill-[#3F59E4] dark:fill-[#99A7F1]" d="M23.201 17.885h17.885c1.787 0 2.746 2.102 1.575 3.453l-19.073 21.99c-1.33 1.532-3.835.4-3.568-1.607L23.2 17.885z" />
      </svg>;
    const LayersIcon = () => <svg width="24" height="24" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
        <path className="fill-[#3F59E4] dark:fill-[#99A7F1]" d="M34.54 29.135l6.373 3.183c1.566.782 1.566 3.017 0 3.8l-14.815 7.396a4.623 4.623 0 01-4.125 0L7.174 36.12c-1.565-.782-1.565-3.017 0-3.798l6.532-3.214" />
        <path className="fill-[#AAB6F3] dark:fill-[#3449BA]" d="M34.54 18.86l6.373 3.183c1.566.782 1.566 3.016 0 3.8L26.098 33.24a4.623 4.623 0 01-4.125 0L7.174 25.843c-1.565-.781-1.565-3.016 0-3.798l6.33-3.164" />
        <path className="fill-[#CFD6F8] dark:fill-[#22307C]" d="M21.94 23.058L7.306 15.745c-1.62-.81-1.62-3.123 0-3.932l14.631-7.319a4.693 4.693 0 014.194 0l14.648 7.319c1.622.81 1.62 3.124 0 3.932L26.13 23.058c-1.321.66-2.873.66-4.191 0z" />
      </svg>;
    const GithubIcon = () => <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="w-5 h-5">
        <path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path>
      </svg>;
    function IconTile({children}) {
      return <div className="
            shrink-0 grid place-items-center w-10 h-10 rounded-lg
            bg-indigo-50 ring-1 ring-indigo-200/60
            dark:bg-indigo-950/40 dark:ring-white/10
          ">
          {children}
        </div>;
    }
    function Card({className = "", children}) {
      return <div className={`rounded-2xl shadow-sm ring-1 ring-zinc-200 dark:ring-zinc-800 ${className}`}>{children}</div>;
    }
    function Button({variant = "primary", type = "button", onClick, children}) {
      const base = "inline-flex items-center justify-center gap-2 h-10 px-4 rounded-xl font-medium transition";
      let styles = "";
      if (variant === "primary") {
        styles = "mint-bg-indigo-600 text-white hover:mint-bg-indigo-700";
      } else if (variant === "outline") {
        styles = "border border-zinc-300 dark:border-zinc-700 mint-bg-transparent hover:mint-bg-zinc-50 dark:hover:mint-bg-zinc-800";
      } else if (variant === "ghost") {
        styles = "hover:mint-bg-zinc-100 dark:hover:mint-bg-zinc-800";
      }
      return <button type={type} onClick={onClick} className={`${base} ${styles}`}>
          {children}
        </button>;
    }
    function Input({id, label, value, onChange, placeholder, name}) {
      return <label className="block space-y-1">
          <span className="text-sm text-zinc-700 dark:text-zinc-300">{label}</span>
          <input id={id} name={name} className="w-full h-11 px-3 rounded-xl border border-zinc-300 dark:border-zinc-700 bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-indigo-500" placeholder={placeholder} value={value} onChange={e => onChange(e.target.value)} />
        </label>;
    }
    function Select({label, value, onChange, options}) {
      return <label className="block space-y-1 max-w-[300px]">
          <span className="text-sm text-zinc-700 dark:text-zinc-300">{label}</span>
          <div className="relative">
            <select className="w-full h-11 appearance-none px-3 pr-9 rounded-xl border border-zinc-300 dark:border-zinc-700 bg-white dark:bg-zinc-900 text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-indigo-500" value={value} onChange={e => onChange(e.target.value)}>
              <optgroup label="Generic Applications">
                {options.map(o => <option key={o.id} value={o.id}>
                    {o.name}
                  </option>)}
              </optgroup>
            </select>
            <svg className="pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 w-5 h-5 text-zinc-500" viewBox="0 0 24 24">
              <path d="M7 10l5 5 5-5z" fill="currentColor" />
            </svg>
          </div>
        </label>;
    }
    function Toast({open, onClose, children}) {
      useEffect(() => {
        if (!open) return;
        const t = setTimeout(onClose, 2200);
        return () => clearTimeout(t);
      }, [open, onClose]);
      return <div className={`fixed right-4 top-4 z-50 transition ${open ? "opacity-100 translate-y-0" : "opacity-0 -translate-y-2 pointer-events-none"}`}>
          <div className="flex items-center gap-2 rounded-xl shadow ring-1 ring-emerald-200 bg-white dark:bg-zinc-900 px-4 py-2">
            <span className="w-1.5 h-8 rounded-l bg-emerald-500" />
            <svg className="w-5 h-5 text-emerald-600" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
              <path d="M20 6L9 17l-5-5" />
            </svg>
            <span className="text-sm text-zinc-900 dark:text-zinc-100">{children}</span>
          </div>
        </div>;
    }
    function Flows() {
      const [route, setRoute] = useState("menu");
      const [apps, setApps] = useState(loadApps());
      const [cfg, setCfg] = useState(loadCfg());
      const [selected, setSelected] = useState(apps[0]?.id || "");
      const [toast, setToast] = useState(false);
      const [bc] = useState(() => mkChannel());
      useEffect(() => {
        if (!apps.find(a => a.id === selected)) {
          setSelected(apps[0]?.id || "");
        }
      }, [apps, selected]);
      useEffect(() => {
        const onMsg = e => {
          const {type, payload} = e.data || ({});
          switch (type) {
            case "NAV":
              setRoute(payload.route);
              break;
            case "SELECT":
              setSelected(payload.appId);
              break;
            case "APPS_UPDATED":
              setApps(loadApps());
              break;
            case "CFG_UPDATED":
              setCfg(loadCfg());
              setToast(true);
              break;
            default:
              break;
          }
        };
        bc.addEventListener("message", onMsg);
        return () => bc.removeEventListener("message", onMsg);
      }, [bc]);
      const nav = nextRoute => {
        setRoute(nextRoute);
        bc.postMessage({
          type: "NAV",
          payload: {
            route: nextRoute
          }
        });
      };
      const selectApp = appId => {
        setSelected(appId);
        bc.postMessage({
          type: "SELECT",
          payload: {
            appId
          }
        });
      };
      const onCreate = name => {
        const id = uid();
        const next = [...apps, {
          id,
          name: name || "Untitled"
        }];
        setApps(next);
        saveApps(next);
        bc.postMessage({
          type: "APPS_UPDATED"
        });
        selectApp(id);
        nav("integrate");
      };
      const onSaveCfg = (appId, data) => {
        const next = {
          ...cfg,
          [appId]: data
        };
        setCfg(next);
        saveCfg(next);
        setToast(true);
        bc.postMessage({
          type: "CFG_UPDATED"
        });
      };
      return <div>
          {route === "menu" && <Menu onCreate={() => nav("create")} onIntegrate={() => nav("integrate")} />}

          {route === "create" && <CreateForm onCancel={() => nav("menu")} onSave={onCreate} />}

          {route === "integrate" && <IntegrateForm apps={apps} selected={selected} onSelect={selectApp} saved={cfg[selected]} onSave={data => onSaveCfg(selected, data)} onCancel={() => nav("menu")} />}

          <Toast open={toast} onClose={() => setToast(false)}>
            Successfully saved your changes.
          </Toast>
        </div>;
    }
    function Menu({onCreate, onIntegrate}) {
      return <ul className="space-y-4 list-none login_list">
          <li className="list-none !px-0">
            <button onClick={onCreate} className="w-full text-left">
              <Card className="p-5 hover:shadow-md transition">
                <div className="flex items-center justify-between">
                  <div className="flex items-center gap-4">
                    <IconTile>
                      <LightningIcon />
                    </IconTile>
                    <h2 className="text-lg">Create a new application</h2>
                  </div>
                  <RightChevron className="w-4 h-4 text-zinc-500" />
                </div>
              </Card>
            </button>
          </li>
          <li className="list-none !px-0">
            <button onClick={onIntegrate} className="w-full text-left">
              <Card className="p-5 hover:shadow-md transition">
                <div className="flex items-center justify-between">
                  <div className="flex items-center gap-4">
                    <IconTile>
                      <LayersIcon />
                    </IconTile>
                    <h2 className="text-lg">Integrate with an existing application</h2>
                  </div>
                  <RightChevron className="w-4 h-4 text-zinc-500" />
                </div>
              </Card>
            </button>
          </li>
          <li className="list-none !px-0">
            <a className="no_external_icon block" href={sampleApp ? sampleApp : "/"} target="_blank" rel="noreferrer">
              <Card className="p-5 hover:shadow-md transition">
                <div className="flex items-center justify-between">
                  <div className="flex items-center gap-4">
                    <IconTile>
                      <GithubIcon />
                    </IconTile>
                    <h2 className="text-lg">View a sample application</h2>
                  </div>
                  <RightChevron className="w-4 h-4 text-zinc-500" />
                </div>
              </Card>
            </a>
          </li>
        </ul>;
    }
    function CreateForm({onSave, onCancel}) {
      const [name, setName] = useState("");
      return <div className="space-y-6">
          <Input id="app-name" label="Application Name" placeholder="My App" value={name} onChange={setName} />
          <p className="text-sm text-zinc-500">You can change this later in the application settings.</p>
          <div className="flex gap-3">
            <Button onClick={() => onSave(name)}>Save</Button>
            <Button variant="outline" onClick={onCancel}>
              Cancel
            </Button>
          </div>
        </div>;
    }
    function IntegrateForm({apps, selected, onSelect, saved, onSave, onCancel}) {
      const [callbacks, setCallbacks] = useState(saved?.callbacks ?? "");
      const [logouts, setLogouts] = useState(saved?.logouts ?? "");
      const [origins, setOrigins] = useState(saved?.origins ?? "");
      useEffect(() => {
        setCallbacks(loadCfg()[selected]?.callbacks ?? "");
        setLogouts(loadCfg()[selected]?.logouts ?? "");
        setOrigins(loadCfg()[selected]?.origins ?? "");
      }, [selected]);
      return <div className="space-y-6">
          <div>
            <span className="block text-sm text-zinc-600 dark:text-zinc-300 mb-1">Select your Application</span>
            <Select label="" value={selected} onChange={onSelect} options={apps} />
          </div>

          <form className="space-y-4" onSubmit={e => {
        e.preventDefault();
        onSave({
          callbacks,
          logouts,
          origins
        });
      }}>
            <Input id="callbacks" name="callbacks" label="Callback URLs" placeholder="http://localhost:3000" value={callbacks} onChange={setCallbacks} />
            <Input id="logout" name="allowed_logout_urls" label="Logout URLs" placeholder="http://localhost:3000" value={logouts} onChange={setLogouts} />
            <Input id="origins" name="web_origins" label="Allowed Web Origins" placeholder="http://localhost:3000" value={origins} onChange={setOrigins} />

            <div className="flex gap-3 pt-2">
              <Button type="submit">Save</Button>
              <Button variant="outline" type="button" onClick={onCancel}>
                Cancel
              </Button>
            </div>
          </form>
        </div>;
    }
    return <div className="w-full mx-auto py-8">
        <Flows />
      </div>;
  }
  ;
  function SignUpFormInternal() {
    return <div className="flex flex-col gap-2 items-center h-full">
        <img noZoom src="/docs/img/quickstarts/action_hero_dashboard.svg" alt="Sign up for an Auth0 account" style={{
      width: "250px",
      height: "250px"
    }} />
        <span className="text-center" style={{
      width: "400px"
    }}>
          Sign up for an{" "}
          <a href="https://auth0.com/signup" target="_blank" rel="noopener noreferrer">
            Auth0 account
          </a>{" "}
          or{" "}
          <span className="font-semibold text-primary dark:text-white cursor-pointer" onClick={() => console.log("log in")}>
            log in
          </span>{" "}
          to your existing account to integrate directly with your own tenant.
        </span>
        <button onClick={() => console.log("sign up")} className="bg-primary dark:bg-primary-light text-white dark:text-black px-4 py-2 rounded-md mt-4 font-medium" style={{
      width: "140px"
    }}>
          Sign up
        </button>
      </div>;
  }
  ;
  return <></>;
};

export const SideMenuSectionItem = ({id, children}) => {
  return <div id={`side-menu-item-${id}`} className="recipe-side-menu-item flex flex-col w-full h-full">
      {children}
    </div>;
};

export const SideMenu = ({sections, children}) => {
  const [visibleSection, setVisibleSection] = useState(sections[0]?.id ?? null);
  const checkVisibility = () => {
    let currentVisible = null;
    const viewportHeight = window.innerHeight;
    const scrollY = window.scrollY;
    sections.forEach(({id}) => {
      const section = document.getElementById(id);
      if (section) {
        const rect = section.getBoundingClientRect();
        const sectionTop = rect.top + scrollY;
        const sectionBottom = sectionTop + rect.height;
        const multiplier = viewportHeight > 1600 ? 0.34 : 0.22;
        if (scrollY + viewportHeight * multiplier >= sectionTop && scrollY <= sectionBottom) {
          currentVisible = id;
        }
      }
    });
    if (currentVisible && currentVisible !== visibleSection) {
      setVisibleSection(currentVisible);
    }
  };
  useEffect(() => {
    const throttledCheck = () => {
      setTimeout(checkVisibility, 100);
    };
    checkVisibility();
    window.addEventListener("scroll", throttledCheck);
    return () => {
      window.removeEventListener("scroll", throttledCheck);
    };
  }, [sections, visibleSection]);
  useEffect(() => {
    sections.forEach(({id}) => {
      const section = document.getElementById(id);
      const sideMenuItem = document.getElementById(`side-menu-item-${id}`);
      if (section) {
        if (id === visibleSection) {
          section.classList.add("active-section");
        } else {
          section.classList.remove("active-section");
        }
      }
      if (sideMenuItem) {
        if (id === visibleSection) {
          sideMenuItem.classList.add("active-side-menu-item");
        } else {
          sideMenuItem.classList.remove("active-side-menu-item");
        }
      }
    });
  }, [visibleSection, sections]);
  return <div className="recipe-side-menu sticky px-2 py-1" style={{
    height: "calc(100vh - 7rem)",
    top: "7rem",
    scrollMarginTop: "var(--scroll-mt)"
  }}>
      {children.map(child => {
    if (child.props.id === visibleSection) {
      return child;
    }
    return null;
  })}
    </div>;
};

export const Section = ({id, title, stepNumber, children, isSingleColumn = false}) => {
  return <div id={id} className={`recipe-section flex flex-col transition-opacity duration-200`}>
      {}
      <Step title={title} stepNumber={stepNumber} titleSize="h3">
        {children}
      </Step>
    </div>;
};

export const Content = ({title, children}) => {
  return <div className="recipe-content flex flex-col">
      {title && <h1 className="text-3xl">{title}</h1>}
      {children}
    </div>;
};

export const Recipe = ({children, isSingleColumn = false}) => {
  return <div className={`pl-4 recipe-container mx-auto grid grid-cols-1 gap-10 relative ${isSingleColumn ? "md:grid-cols-1" : "md:grid-cols-2"}`}>
      {children}
    </div>;
};

<QuickstartButtons githubLink="https://github.com/auth0-samples/auth0-ionic-samples/tree/main/react" lang="fr-ca" />

export const sections = [{
  id: "démarrage",
  title: "Démarrage"
}, {
  id: "configuration-d-auth0",
  title: "Configuration d’Auth0"
}, {
  id: "installer-la-trousse-sdk-react-auth0",
  title: "Installer la trousse SDK React Auth0"
}, {
  id: "configurer-le-composant-auth0provider",
  title: "Configurer le composant Auth0Provider"
}, {
  id: "ajouter-une-fonctionnalité-de-connexion-à-votre-application",
  title: "Ajouter une fonctionnalité de connexion à votre application"
}, {
  id: "gérer-le-rappel-de-connexion",
  title: "Gérer le rappel de connexion"
}, {
  id: "ajouter-une-fonctionnalité-de-déconnexion-à-votre-application",
  title: "Ajouter une fonctionnalité de déconnexion à votre application"
}, {
  id: "afficher-le-profil-utilisateur",
  title: "Afficher le profil utilisateur"
}];

<Recipe>
  <Content>
    Auth0 vous permet d’ajouter rapidement l’authentification et de pouvoir accéder aux informations relatives au profil utilisateur dans votre application. Ce guide explique comment intégrer Auth0 avec une application Ionic (React) & Capacitor en utilisant la [trousse SDK Auth0 React](https://github.com/auth0/auth0-react).

    <Section id={sections[0].id} title={sections[0].title} stepNumber="1">
      Ce guide de démarrage rapide suppose que vous avez déjà une application [Ionic](https://ionicframework.com/) en cours d’exécution avec [Capacitor](https://capacitorjs.com/). Si ce n’est pas le cas, consultez [Using Capacitor with Ionic Framework guide (Utiliser Capacitor avec le cadre d’applications Ionic)](https://capacitorjs.com/docs/getting-started/with-ionic)  pour commencer avec une application simple ou clonez nos [our sample apps (exemples d’applications)](https://github.com/auth0-samples/auth0-ionic-samples).

      Vous devez également être familiarisé avec [Capacitor development workflow (le flux de production de développement Capacitor)](https://capacitorjs.com/docs/basics/workflow).
    </Section>

    <Section id={sections[1].id} title={sections[1].title} stepNumber="2">
      Pour utiliser les services Auth0, vous devez avoir une application installée dans Auth0 Dashboard. L’application Auth0 est l’endroit où vous allez configurer le fonctionnement de l’authentification pour votre projet.

      <Info>
        Tout au long de cet article, `YOUR\_PACKAGE\_ID` est l’identifiant du package de votre application. Ceci peut être trouvé et configuré dans le champ `appId` de votre fichier `capacitor.config.ts` . Voir [Capacitor’s Config schema (Schéma de configuration du Capacitor)](https://capacitorjs.com/docs/config#schema) pour plus d’informations.
      </Info>

      ### Configurer une application

      Utilisez le sélecteur interactif pour créer une nouvelle application Auth0 ou sélectionner une application existante qui représente le projet avec lequel vous souhaitez effectuer l’intégration. Dans Auth0, il est attribué à chaque application un identifiant client unique alphanumérique que votre code d’application utilisera pour appeler les API Auth0 via la trousse SDK.

      Tous les paramètres que vous configurez à l’aide de ce guide rapide seront automatiquement mis à jour pour votre application dans le [Dashboard](https://manage.auth0.com/#/), qui est l’endroit où vous pourrez gérer vos applications à l’avenir.

      Si vous préférez explorer une configuration complète, consultez plutôt un exemple d’application.

      ### Configuration des URL de rappel

      Une URL de rappel est une URL intégrée dans votre application vers laquelle vous souhaitez qu’Auth0 redirige les utilisateurs après leur authentification. Si elle n’est pas définie, les utilisateurs ne seront pas redirigés vers votre application après s’être connectés.

      <Info>
        Si vous suivez notre projet à titre d’exemple, définissez ceci sur :
        `YOUR\_PACKAGE\_ID://{yourTenant}.auth0.com/capacitor/YOUR\_PACKAGE\_ID/callback`.
      </Info>

      ### Configuration des URL de déconnexion

      Une URL de déconnexion est une URL intégrée dans votre application vers laquelle vous souhaitez qu’Auth0 redirige les utilisateurs après leur déconnexion. Si elle n’est pas définie, les utilisateurs ne pourront pas se déconnecter de votre application et recevront un message d’erreur.

      <Info>
        Si vous suivez notre projet à titre d’exemple, définissez ceci sur :
        `YOUR\_PACKAGE\_ID://{yourTenant}.auth0.com/capacitor/YOUR\_PACKAGE\_ID/callback`.
      </Info>

      ### Configurer les origines autorisées

      Pour pouvoir faire des requêtes à partir de votre application d’origine vers Auth0, définissez les **origines autorisées** dans vos [Application Settings (Paramètres d’application)](https://manage.auth0.com/dashboard/#/applications/%7ByourClientId%7D/settings).

      <Info>
        Si vous suivez notre projet faisant office d’exemple, définissez ceci sur `capacitor://localhost, http://localhost` pour iOS et Android respectivement.
      </Info>

      Enfin, assurez-vous que le **type d’application** pour votre application est défini sur **Native** dans les [Application Settings (Paramètres d’application)](https://manage.auth0.com/dashboard/#/applications/%7ByourClientId%7D/settings).
    </Section>

    <Section id={sections[2].id} title={sections[2].title} stepNumber="3">
      Exécutez la commande suivante dans le répertoire de votre projet pour installer la trousse SDK React Auth0 :

      `npm install @auth0/auth0-react`

      La trousse SDK expose des méthodes et variables qui vous aident à intégrer Auth0 avec votre application React en utilisant les [Crochets React](https://reactjs.org/docs/hooks-overview.html) ou les [Composants d’ordre supérieur](https://reactjs.org/docs/higher-order-components.html).

      ### Installer les plugiciels Capacitor

      Ce guide rapide et cet exemple utilisent certains des plugiciels officiels Capacitor. Installez-les dans votre application à l’aide de la commande suivante :

      `npm install @capacitor/browser @capacitor/app`

      * [`@capacitor/browser`](https://capacitorjs.com/docs/apis/browser) : Vous permet d’interagir avec le navigateur de système de l’appareil, et est utilisé pour ouvrir l’URL vers le point de terminaison d’autorisation d’Auth0.
      * [`@capacitor/app`](https://capacitorjs.com/docs/apis/app) : Vous permet de vous abonner à des événements d’application de haut niveau, utiles pour la gestion des Callbacks depuis Auth0.

      <Info>
        Le plugiciel de navigateur de Capacitor sur iOS utilise [`SFSafariViewController`](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller), qui sur iOS 11+ ne partage pas les témoins avec Safari sur l’appareil. Cela signifie que SSO ne fonctionnera pas sur ces appareils. Si vous avez besoin de SSO, veuillez utiliser un plugiciel compatible qui utilise [ASWebAuthenticationSession](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession).
      </Info>
    </Section>

    <Section id={sections[3].id} title={sections[3].title} stepNumber="4">
      Au cours de son fonctionnement, la trousse SDK React Auth0 utilise [React Context](https://reactjs.org/docs/context.html) pour gérer l’état d’authentification de vos utilisateurs. Une façon d’intégrer Auth0 avec votre application React est d’envelopper votre composant racine avec un `Auth0Provider` que vous pouvez importer à partir de la trousse SDK.

      Le composant `Auth0Provider` prend les props suivants :

      * `domain` : La valeur du `domain` présente dans les **paramètres** de l’application que vous avez créée dans votre Auth0 Dashboard, ou votre domaine personnalisé si vous utilisez la fonctionnalité Domaines personnalisés d’Auth0.
      * `clientId` : La valeur de l’identifiant du client présente dans les **paramètres** de l’application que vous avez créée dans votre Auth0 Dashboard.
      * `useRefreshTokens` : Pour utiliser auth0-react avec Ionic sur Android et iOS, il est nécessaire d’activer les jetons d’actualisation.
      * `useRefreshTokensFallback` : Pour utiliser auth0-react avec Ionic sur Android et iOS, il est nécessaire de désactiver le iframe de substitution.
      * `authorizationParams.redirect_uri` : L’URL vers laquelle vous souhaitez rediriger vos utilisateurs après qu’ils se soient authentifiés avec Auth0.

      <Warning>
        Pour conserver l’authentification après la fermeture et la réouverture de l’application, vous pouvez définir `cacheLocation` sur `localstorage` lors de la configuration du SDK, mais soyez conscient des [risques liés au stockage de jetons dans localstorage](/docs/fr-ca/libraries/auth0-single-page-app-sdk#change-storage-options). De plus, localstorage devrait être traité comme **transitoire** dans l’application Capacitor car les données pourraient être récupérées de façon inattendue dans certaines circonstances. Veuillez lire les [directives sur le stockage dans la documentation Capacitor](https://capacitorjs.com/docs/guides/storage#why-cant-i-just-use-localstorage-or-indexeddb).
        En outre, le SDK a la capacité [d’utiliser une implémentation de cache personnalisée](https://github.com/auth0/auth0-spa-js/blob/master/EXAMPLES.md#creating-a-custom-cache) pour stocker des jetons, si vous avez une exigence d’utiliser un mécanisme de stockage plus sûr et persistant.
        **Notez** que nous recommandons **de ne pas** utiliser le [plugiciel Capacitor pour stocker](https://capacitorjs.com/docs/apis/storage) les jetons, car cela est soutenu par [UserDefaults](https://developer.apple.com/documentation/foundation/userdefaults) et [SharedPreferences](https://developer.android.com/reference/android/content/SharedPreferences) sur iOS et Android respectivement. Les données stockées à l’aide de ces API ne sont pas cryptées, non sécurisées et peuvent également être synchronisées dans le nuage.
      </Warning>

      <Note>
        ##### Point de contrôle

        Ajoutez le composant `Auth0Provider` d’une manière qui enveloppe votre composant `App`, puis exécutez votre application pour vérifier que le SDK est initialisé correctement et que votre application ne lance pas d’erreurs liées à Auth0.
      </Note>
    </Section>

    <Section id={sections[4].id} title={sections[4].title} stepNumber="5">
      Dans une application Capacitor, le plugiciel [Capacitor’s Browser](https://capacitorjs.com/docs/apis/browser) effectue une redirection vers la [Universal Login Page (page de connexion universelle) d’Auth0](https://auth0.com/universal-login) Auth0. Définissez le paramètre `openUrl` sur la fonction `loginWithRedirect` pour utiliser `Browser.open` afin que l’URL soit ouverte à l’aide du composant de navigateur système de l’appareil ([SFSafariViewController](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller) sur iOS et [Chrome Custom Tabs \[Onglets personnalisés Chrome\]](https://developer.chrome.com/docs/android/custom-tabs) sur Android).

      <Info>
        Par défaut, la méthode `loginWithRedirect` de la trousse SDK utilise `window.location.href` pour accéder à la page de connexion dans l’application de navigateur par défaut sur l’appareil de l’utilisateur plutôt que dans le composant de navigateur système approprié pour la plate-forme. L’utilisateur quitterait votre application pour s’authentifier et pourrait rendre l’expérience utilisateur sous-optimale.
      </Info>

      <Note>
        ##### Point de contrôle

        La fonction `loginWithRedirect` indique à la trousse SDK d’initier le flux de connexion, en utilisant la fonction `Browser.open` pour ouvrir l’URL de connexion avec le composant navigateur du système de la plateforme en définissant le paramètre `openUrl`. Cela permet à votre utilisateur de se connecter à votre application. Les utilisateurs sont redirigés vers la page de connexion à Auth0 et ne reçoivent aucune erreur.
      </Note>
    </Section>

    <Section id={sections[5].id} title={sections[5].title} stepNumber="6">
      Une fois que les utilisateurs sont connectés avec la page de connexion universelle, ils sont redirigés vers votre application au moyen d’une URL avec un schéma d’URL personnalisé. L’événement `appUrlOpen` doit être traité au sein de votre application. Vous pouvez appeler la méthode `handleRedirectCallback` à partir de la trousse SDK Auth0 pour initialiser l’état d’authentification.

      Vous pouvez utiliser cette méthode uniquement sur une redirection depuis Auth0. Vérifiez que les paramètres `code` et `state` sont présents dans l’URL.

      La méthode `Browser.close()` devrait fermer le navigateur lorsque cet événement est déclenché.

      <Info>
        Cet article suppose que vous utiliserez des schémas d’URL personnalisés pour gérer le rappel dans votre application. Pour ce faire, enregistrez votre `YOUR\_PACKAGE\_ID` comme schéma d’URL pour la plateforme de votre choix. Pour en savoir plus, lire [Defining a Custom URL Scheme (Définition d’un schéma d’URL personnalisé)](https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app) pour iOS ou [Create Deep Links to App Content (Création de liens profonds vers le contenu des applications)](https://developer.android.com/training/app-links/deep-linking) pour Android.
      </Info>

      <Note>
        ##### Point de contrôle

        Ajoutez `appUrlOpen` au composant `App` de votre application et connectez-vous. La fenêtre du navigateur devrait se fermer une fois que l’utilisateur s’authentifie et se connecte à votre application.
      </Note>
    </Section>

    <Section id={sections[6].id} title={sections[6].title} stepNumber="7">
      Maintenant que les utilisateurs peuvent se connecter, vous devez configurer [une façon de se déconnecter](https://auth0.com/docs/logout/guides/logout-auth0). Les utilisateurs doivent être redirigés vers le point de terminaison de déconnexion Auth0 dans le navigateur pour effacer leur session de navigation. Encore une fois, le plugiciel du navigateur de Capacitor doit effectuer cette redirection afin que l’utilisateur ne quitte pas votre application et ne vive pas une expérience frustrante.

      Pour y parvenir avec Ionic et Capacitor en conjonction avec le SDK Auth0 :

      * Créez l’URL de votre application vers laquelle Auth0 doit rediriger après la déconnexion. Il s’agit d’une URL qui utilise votre schéma personnalisé enregistré et le domaine Auth0. Ajoutez-la à votre configuration **URL de déconnexions autorisées** dans Auth0 Dashboard
      * Déconnectez-vous de la trousse SDK en appelant `logout` et transmettez votre URL de redirection comme paramètre `logoutParams.returnTo`.
      * Définissez le paramètre `openUrl` sur un callback qui utilise le plugiciel de navigateur Capacitor pour ouvrir l’URL à l’aide de `Browser.open`.

      <Info>
        De la même manière que pour l’étape de connexion, si vous ne définissez pas `openUrl` lors de l’appel de `logout`, le SDK redirige l’utilisateur vers l’URL de déconnexion à l’aide de l’application de navigateur par défaut sur l’appareil, ce qui offre une expérience utilisateur sous-optimale.
      </Info>

      <Note>
        ##### Point de contrôle

        Fournir un moyen pour vos utilisateurs de se déconnecter de votre application. Vérifiez que vous redirigez vers Auth0, puis vers l’adresse spécifiée dans le paramètre `returnTo`. Vérifiez que vous n’êtes plus connecté à votre application.
      </Note>
    </Section>

    <Section id={sections[7].id} title={sections[7].title} stepNumber="8">
      La trousse SDK React Auth0 récupère le user’s profile (profil utilisateur) associé aux utilisateurs connectés dans n’importe quel composant dont vous avez besoin, comme leur nom ou leur image de profil, pour personnaliser l’interface utilisateur. Les informations de profil sont accessibles via la propriété `user` exposée par l’appel `useAuth0()`.

      L’initialisation de la trousse SDK est asynchrone, et vous devez protéger le profil utilisateur en activant les propriétés `isLoading` et `user`. Une fois que `isLoading` est `false` et que `user` a une valeur, le profil utilisateur peut être utilisé.

      <Note>
        ##### Point de contrôle

        Fournir un moyen pour que vos utilisateurs puissent voir leurs détails de profil utilisateur dans l’application et vérifiez que vous êtes en mesure de récupérer et d’afficher les informations de votre profil à l’écran une fois que vous avez ouvert une session.
      </Note>
    </Section>

    ## Étapes suivantes

    Beau travail! Si vous en êtes arrivé là, vous devriez avoir la connexion, la déconnexion et les informations de profil utilisateur actives dans votre application.

    Cela conclut notre tutoriel de démarrage rapide, mais il y a tellement plus à explorer. Pour en savoir plus sur ce que vous pouvez faire avec Auth0, consultez :

    * [Auth0 Dashboard](https://manage.auth0.com/#) : apprenez à configurer et gérer votre locataire et vos applications Auth0
    * [Auth0 Marketplace](https://marketplace.auth0.com/) : découvrez des intégrations que vous pouvez activer pour étendre les fonctionnalités d’Auth0
  </Content>

  <SideMenu sections={sections}>
    <SideMenuSectionItem id={sections[0].id}>
      <SignUpForm lang="fr" />
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[1].id}>
      <SignUpForm lang="fr" />
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[2].id}>
      <SignUpForm lang="fr" />
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[3].id}>
      <AuthCodeGroup>
        ```tsx index.tsx lines  theme={null}
        import React from 'react';
        import { createRoot } from 'react-dom/client';
        import { Auth0Provider } from '@auth0/auth0-react';
        import App from './App';

        const root = createRoot(document.getElementById('root'));

        root.render(
          <Auth0Provider
            domain="{yourDomain}"
            clientId="{yourClientId}"
            useRefreshTokens={true}
            useRefreshTokensFallback={false}
            authorizationParams={{
              redirect_uri: "YOUR_PACKAGE_ID://{yourDomain}/capacitor/YOUR_PACKAGE_ID/callback"
            }}
          >
            <App />
          </Auth0Provider>
        );
        ```

        ```tsx login-button.tsx lines  theme={null}
        import { useAuth0 } from '@auth0/auth0-react';
        import { Browser } from '@capacitor/browser';
        import { IonButton } from '@ionic/react';

        const LoginButton: React.FC = () => {
          const { loginWithRedirect } = useAuth0();

          const login = async () => {
            await loginWithRedirect({
              async openUrl(url) {
                 // Redirect using Capacitor's Browser plugin
                await Browser.open({
                  url,
                  windowName: "_self"
                });
              }
            });
          };

          return <IonButton onClick={login}>Log in</IonButton>;
        };

        export default LoginButton;
        ```

        ```tsx logout-button.tsx lines  theme={null}
        import { useAuth0 } from '@auth0/auth0-react';
        import { Browser } from '@capacitor/browser';
        import { IonButton } from '@ionic/react';

        // This should reflect the URL added earlier to your "Allowed Logout URLs" setting
        // in the Auth0 dashboard.
        const logoutUri = 'YOUR_PACKAGE_ID://{yourDomain}/capacitor/YOUR_PACKAGE_ID/callback';

        const LogoutButton: React.FC = () => {
          const { logout } = useAuth0();

          const doLogout = async () => {
            await logout({
              logoutParams: {
                returnTo: logoutUri
              },
              async openUrl(url) {
                 // Redirect using Capacitor's Browser plugin
                await Browser.open({
                  url,
                  windowName: "_self"
                });
              }
            });
          };

          return <IonButton onClick={doLogout}>Log out</IonButton>;
        };

        export default LogoutButton;
        ```

        ```tsx app.tsx lines  theme={null}
        // Import Capacitor's app and browser plugins, giving us access to `addListener` and `appUrlOpen`,
        // as well as the bits needed for Auth0 and React
        import { App as CapApp } from '@capacitor/app';
        import { Browser } from '@capacitor/browser';
        import { useEffect } from 'react';
        import { useAuth0 } from '@auth0/auth0-react';

        // ...

        const App: React.FC = () => {
          // Get the callback handler from the Auth0 React hook
          const { handleRedirectCallback } = useAuth0();

          useEffect(() => {
            // Handle the 'appUrlOpen' event and call `handleRedirectCallback`
            CapApp.addListener('appUrlOpen', async ({ url }) => {
              if (url.includes('state') && (url.includes('code') || url.includes('error'))) {
                await handleRedirectCallback(url);
              }
              // No-op on Android
              await Browser.close();
            });
          }, [handleRedirectCallback]);

          // ..
        };// Import Capacitor's app and browser plugins, giving us access to `addListener` and `appUrlOpen`,
        // as well as the bits needed for Auth0 and React
        import { App as CapApp } from '@capacitor/app';
        import { Browser } from '@capacitor/browser';
        import { useEffect } from 'react';
        import { useAuth0 } from '@auth0/auth0-react';

        // ...

        const App: React.FC = () => {
          // Get the callback handler from the Auth0 React hook
          const { handleRedirectCallback } = useAuth0();

          useEffect(() => {
            // Handle the 'appUrlOpen' event and call `handleRedirectCallback`
            CapApp.addListener('appUrlOpen', async ({ url }) => {
              if (url.includes('state') && (url.includes('code') || url.includes('error'))) {
                await handleRedirectCallback(url);
              }
              // No-op on Android
              await Browser.close();
            });
          }, [handleRedirectCallback]);

          // ..
        };
        ```

        ```tsx user-profile.tsx lines  theme={null}
        import { useAuth0 } from '@auth0/auth0-react';

        const Profile: React.FC = () => {
          const { user, isLoading } = useAuth0();

          // If the SDK is not ready, or a user is not authenticated, exit.
          if (isLoading || !user) return null;

          return (
            <div>
              <img src={user.picture} alt={user.name} />
              <h2>{user.name}</h2>
              <p>{user.email}</p>
            </div>
          );
        };

        export default Profile;
        ```
      </AuthCodeGroup>
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[4].id}>
      <AuthCodeGroup>
        ```tsx login-button.tsx lines  theme={null}
        import { useAuth0 } from '@auth0/auth0-react';
        import { Browser } from '@capacitor/browser';
        import { IonButton } from '@ionic/react';

        const LoginButton: React.FC = () => {
          const { loginWithRedirect } = useAuth0();

          const login = async () => {
            await loginWithRedirect({
              async openUrl(url) {
                 // Redirect using Capacitor's Browser plugin
                await Browser.open({
                  url,
                  windowName: "_self"
                });
              }
            });
          };

          return <IonButton onClick={login}>Log in</IonButton>;
        };

        export default LoginButton;
        ```

        ```tsx index.tsx lines  theme={null}
        import React from 'react';
        import { createRoot } from 'react-dom/client';
        import { Auth0Provider } from '@auth0/auth0-react';
        import App from './App';

        const root = createRoot(document.getElementById('root'));

        root.render(
          <Auth0Provider
            domain="{yourDomain}"
            clientId="{yourClientId}"
            useRefreshTokens={true}
            useRefreshTokensFallback={false}
            authorizationParams={{
              redirect_uri: "YOUR_PACKAGE_ID://{yourDomain}/capacitor/YOUR_PACKAGE_ID/callback"
            }}
          >
            <App />
          </Auth0Provider>
        );
        ```

        ```tsx logout-button.tsx lines  theme={null}
        import { useAuth0 } from '@auth0/auth0-react';
        import { Browser } from '@capacitor/browser';
        import { IonButton } from '@ionic/react';

        // This should reflect the URL added earlier to your "Allowed Logout URLs" setting
        // in the Auth0 dashboard.
        const logoutUri = 'YOUR_PACKAGE_ID://{yourDomain}/capacitor/YOUR_PACKAGE_ID/callback';

        const LogoutButton: React.FC = () => {
          const { logout } = useAuth0();

          const doLogout = async () => {
            await logout({
              logoutParams: {
                returnTo: logoutUri
              },
              async openUrl(url) {
                 // Redirect using Capacitor's Browser plugin
                await Browser.open({
                  url,
                  windowName: "_self"
                });
              }
            });
          };

          return <IonButton onClick={doLogout}>Log out</IonButton>;
        };

        export default LogoutButton;
        ```

        ```tsx app.tsx lines  theme={null}
        // Import Capacitor's app and browser plugins, giving us access to `addListener` and `appUrlOpen`,
        // as well as the bits needed for Auth0 and React
        import { App as CapApp } from '@capacitor/app';
        import { Browser } from '@capacitor/browser';
        import { useEffect } from 'react';
        import { useAuth0 } from '@auth0/auth0-react';

        // ...

        const App: React.FC = () => {
          // Get the callback handler from the Auth0 React hook
          const { handleRedirectCallback } = useAuth0();

          useEffect(() => {
            // Handle the 'appUrlOpen' event and call `handleRedirectCallback`
            CapApp.addListener('appUrlOpen', async ({ url }) => {
              if (url.includes('state') && (url.includes('code') || url.includes('error'))) {
                await handleRedirectCallback(url);
              }
              // No-op on Android
              await Browser.close();
            });
          }, [handleRedirectCallback]);

          // ..
        };// Import Capacitor's app and browser plugins, giving us access to `addListener` and `appUrlOpen`,
        // as well as the bits needed for Auth0 and React
        import { App as CapApp } from '@capacitor/app';
        import { Browser } from '@capacitor/browser';
        import { useEffect } from 'react';
        import { useAuth0 } from '@auth0/auth0-react';

        // ...

        const App: React.FC = () => {
          // Get the callback handler from the Auth0 React hook
          const { handleRedirectCallback } = useAuth0();

          useEffect(() => {
            // Handle the 'appUrlOpen' event and call `handleRedirectCallback`
            CapApp.addListener('appUrlOpen', async ({ url }) => {
              if (url.includes('state') && (url.includes('code') || url.includes('error'))) {
                await handleRedirectCallback(url);
              }
              // No-op on Android
              await Browser.close();
            });
          }, [handleRedirectCallback]);

          // ..
        };
        ```

        ```tsx user-profile.tsx lines  theme={null}
        import { useAuth0 } from '@auth0/auth0-react';

        const Profile: React.FC = () => {
          const { user, isLoading } = useAuth0();

          // If the SDK is not ready, or a user is not authenticated, exit.
          if (isLoading || !user) return null;

          return (
            <div>
              <img src={user.picture} alt={user.name} />
              <h2>{user.name}</h2>
              <p>{user.email}</p>
            </div>
          );
        };

        export default Profile;
        ```
      </AuthCodeGroup>
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[5].id}>
      <AuthCodeGroup>
        ```tsx app.tsx lines  theme={null}
        // Import Capacitor's app and browser plugins, giving us access to `addListener` and `appUrlOpen`,
        // as well as the bits needed for Auth0 and React
        import { App as CapApp } from '@capacitor/app';
        import { Browser } from '@capacitor/browser';
        import { useEffect } from 'react';
        import { useAuth0 } from '@auth0/auth0-react';

        // ...

        const App: React.FC = () => {
          // Get the callback handler from the Auth0 React hook
          const { handleRedirectCallback } = useAuth0();

          useEffect(() => {
            // Handle the 'appUrlOpen' event and call `handleRedirectCallback`
            CapApp.addListener('appUrlOpen', async ({ url }) => {
              if (url.includes('state') && (url.includes('code') || url.includes('error'))) {
                await handleRedirectCallback(url);
              }
              // No-op on Android
              await Browser.close();
            });
          }, [handleRedirectCallback]);

          // ..
        };// Import Capacitor's app and browser plugins, giving us access to `addListener` and `appUrlOpen`,
        // as well as the bits needed for Auth0 and React
        import { App as CapApp } from '@capacitor/app';
        import { Browser } from '@capacitor/browser';
        import { useEffect } from 'react';
        import { useAuth0 } from '@auth0/auth0-react';

        // ...

        const App: React.FC = () => {
          // Get the callback handler from the Auth0 React hook
          const { handleRedirectCallback } = useAuth0();

          useEffect(() => {
            // Handle the 'appUrlOpen' event and call `handleRedirectCallback`
            CapApp.addListener('appUrlOpen', async ({ url }) => {
              if (url.includes('state') && (url.includes('code') || url.includes('error'))) {
                await handleRedirectCallback(url);
              }
              // No-op on Android
              await Browser.close();
            });
          }, [handleRedirectCallback]);

          // ..
        };
        ```

        ```tsx index.tsx lines  theme={null}
        import React from 'react';
        import { createRoot } from 'react-dom/client';
        import { Auth0Provider } from '@auth0/auth0-react';
        import App from './App';

        const root = createRoot(document.getElementById('root'));

        root.render(
          <Auth0Provider
            domain="{yourDomain}"
            clientId="{yourClientId}"
            useRefreshTokens={true}
            useRefreshTokensFallback={false}
            authorizationParams={{
              redirect_uri: "YOUR_PACKAGE_ID://{yourDomain}/capacitor/YOUR_PACKAGE_ID/callback"
            }}
          >
            <App />
          </Auth0Provider>
        );
        ```

        ```tsx login-button.tsx lines  theme={null}
        import { useAuth0 } from '@auth0/auth0-react';
        import { Browser } from '@capacitor/browser';
        import { IonButton } from '@ionic/react';

        const LoginButton: React.FC = () => {
          const { loginWithRedirect } = useAuth0();

          const login = async () => {
            await loginWithRedirect({
              async openUrl(url) {
                 // Redirect using Capacitor's Browser plugin
                await Browser.open({
                  url,
                  windowName: "_self"
                });
              }
            });
          };

          return <IonButton onClick={login}>Log in</IonButton>;
        };

        export default LoginButton;
        ```

        ```tsx logout-button.tsx lines  theme={null}
        import { useAuth0 } from '@auth0/auth0-react';
        import { Browser } from '@capacitor/browser';
        import { IonButton } from '@ionic/react';

        // This should reflect the URL added earlier to your "Allowed Logout URLs" setting
        // in the Auth0 dashboard.
        const logoutUri = 'YOUR_PACKAGE_ID://{yourDomain}/capacitor/YOUR_PACKAGE_ID/callback';

        const LogoutButton: React.FC = () => {
          const { logout } = useAuth0();

          const doLogout = async () => {
            await logout({
              logoutParams: {
                returnTo: logoutUri
              },
              async openUrl(url) {
                 // Redirect using Capacitor's Browser plugin
                await Browser.open({
                  url,
                  windowName: "_self"
                });
              }
            });
          };

          return <IonButton onClick={doLogout}>Log out</IonButton>;
        };

        export default LogoutButton;
        ```

        ```tsx user-profile.tsx lines  theme={null}
        import { useAuth0 } from '@auth0/auth0-react';

        const Profile: React.FC = () => {
          const { user, isLoading } = useAuth0();

          // If the SDK is not ready, or a user is not authenticated, exit.
          if (isLoading || !user) return null;

          return (
            <div>
              <img src={user.picture} alt={user.name} />
              <h2>{user.name}</h2>
              <p>{user.email}</p>
            </div>
          );
        };

        export default Profile;
        ```
      </AuthCodeGroup>
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[6].id}>
      <AuthCodeGroup>
        ```tsx logout-button.tsx lines  theme={null}
        import { useAuth0 } from '@auth0/auth0-react';
        import { Browser } from '@capacitor/browser';
        import { IonButton } from '@ionic/react';

        // This should reflect the URL added earlier to your "Allowed Logout URLs" setting
        // in the Auth0 dashboard.
        const logoutUri = 'YOUR_PACKAGE_ID://{yourDomain}/capacitor/YOUR_PACKAGE_ID/callback';

        const LogoutButton: React.FC = () => {
          const { logout } = useAuth0();

          const doLogout = async () => {
            await logout({
              logoutParams: {
                returnTo: logoutUri
              },
              async openUrl(url) {
                 // Redirect using Capacitor's Browser plugin
                await Browser.open({
                  url,
                  windowName: "_self"
                });
              }
            });
          };

          return <IonButton onClick={doLogout}>Log out</IonButton>;
        };

        export default LogoutButton;
        ```

        ```tsx index.tsx lines  theme={null}
        import React from 'react';
        import { createRoot } from 'react-dom/client';
        import { Auth0Provider } from '@auth0/auth0-react';
        import App from './App';

        const root = createRoot(document.getElementById('root'));

        root.render(
          <Auth0Provider
            domain="{yourDomain}"
            clientId="{yourClientId}"
            useRefreshTokens={true}
            useRefreshTokensFallback={false}
            authorizationParams={{
              redirect_uri: "YOUR_PACKAGE_ID://{yourDomain}/capacitor/YOUR_PACKAGE_ID/callback"
            }}
          >
            <App />
          </Auth0Provider>
        );
        ```

        ```tsx login-button.tsx lines  theme={null}
        import { useAuth0 } from '@auth0/auth0-react';
        import { Browser } from '@capacitor/browser';
        import { IonButton } from '@ionic/react';

        const LoginButton: React.FC = () => {
          const { loginWithRedirect } = useAuth0();

          const login = async () => {
            await loginWithRedirect({
              async openUrl(url) {
                 // Redirect using Capacitor's Browser plugin
                await Browser.open({
                  url,
                  windowName: "_self"
                });
              }
            });
          };

          return <IonButton onClick={login}>Log in</IonButton>;
        };

        export default LoginButton;
        ```

        ```tsx app.tsx lines  theme={null}
        // Import Capacitor's app and browser plugins, giving us access to `addListener` and `appUrlOpen`,
        // as well as the bits needed for Auth0 and React
        import { App as CapApp } from '@capacitor/app';
        import { Browser } from '@capacitor/browser';
        import { useEffect } from 'react';
        import { useAuth0 } from '@auth0/auth0-react';

        // ...

        const App: React.FC = () => {
          // Get the callback handler from the Auth0 React hook
          const { handleRedirectCallback } = useAuth0();

          useEffect(() => {
            // Handle the 'appUrlOpen' event and call `handleRedirectCallback`
            CapApp.addListener('appUrlOpen', async ({ url }) => {
              if (url.includes('state') && (url.includes('code') || url.includes('error'))) {
                await handleRedirectCallback(url);
              }
              // No-op on Android
              await Browser.close();
            });
          }, [handleRedirectCallback]);

          // ..
        };// Import Capacitor's app and browser plugins, giving us access to `addListener` and `appUrlOpen`,
        // as well as the bits needed for Auth0 and React
        import { App as CapApp } from '@capacitor/app';
        import { Browser } from '@capacitor/browser';
        import { useEffect } from 'react';
        import { useAuth0 } from '@auth0/auth0-react';

        // ...

        const App: React.FC = () => {
          // Get the callback handler from the Auth0 React hook
          const { handleRedirectCallback } = useAuth0();

          useEffect(() => {
            // Handle the 'appUrlOpen' event and call `handleRedirectCallback`
            CapApp.addListener('appUrlOpen', async ({ url }) => {
              if (url.includes('state') && (url.includes('code') || url.includes('error'))) {
                await handleRedirectCallback(url);
              }
              // No-op on Android
              await Browser.close();
            });
          }, [handleRedirectCallback]);

          // ..
        };
        ```

        ```tsx user-profile.tsx lines  theme={null}
        import { useAuth0 } from '@auth0/auth0-react';

        const Profile: React.FC = () => {
          const { user, isLoading } = useAuth0();

          // If the SDK is not ready, or a user is not authenticated, exit.
          if (isLoading || !user) return null;

          return (
            <div>
              <img src={user.picture} alt={user.name} />
              <h2>{user.name}</h2>
              <p>{user.email}</p>
            </div>
          );
        };

        export default Profile;
        ```
      </AuthCodeGroup>
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[7].id}>
      <AuthCodeGroup>
        ```tsx user-profile.tsx lines  theme={null}
        import { useAuth0 } from '@auth0/auth0-react';

        const Profile: React.FC = () => {
          const { user, isLoading } = useAuth0();

          // If the SDK is not ready, or a user is not authenticated, exit.
          if (isLoading || !user) return null;

          return (
            <div>
              <img src={user.picture} alt={user.name} />
              <h2>{user.name}</h2>
              <p>{user.email}</p>
            </div>
          );
        };

        export default Profile;
        ```

        ```tsx index.tsx lines  theme={null}
        import React from 'react';
        import { createRoot } from 'react-dom/client';
        import { Auth0Provider } from '@auth0/auth0-react';
        import App from './App';

        const root = createRoot(document.getElementById('root'));

        root.render(
          <Auth0Provider
            domain="{yourDomain}"
            clientId="{yourClientId}"
            useRefreshTokens={true}
            useRefreshTokensFallback={false}
            authorizationParams={{
              redirect_uri: "YOUR_PACKAGE_ID://{yourDomain}/capacitor/YOUR_PACKAGE_ID/callback"
            }}
          >
            <App />
          </Auth0Provider>
        );
        ```

        ```tsx login-button.tsx lines  theme={null}
        import { useAuth0 } from '@auth0/auth0-react';
        import { Browser } from '@capacitor/browser';
        import { IonButton } from '@ionic/react';

        const LoginButton: React.FC = () => {
          const { loginWithRedirect } = useAuth0();

          const login = async () => {
            await loginWithRedirect({
              async openUrl(url) {
                 // Redirect using Capacitor's Browser plugin
                await Browser.open({
                  url,
                  windowName: "_self"
                });
              }
            });
          };

          return <IonButton onClick={login}>Log in</IonButton>;
        };

        export default LoginButton;
        ```

        ```tsx logout-button.tsx lines  theme={null}
        import { useAuth0 } from '@auth0/auth0-react';
        import { Browser } from '@capacitor/browser';
        import { IonButton } from '@ionic/react';

        // This should reflect the URL added earlier to your "Allowed Logout URLs" setting
        // in the Auth0 dashboard.
        const logoutUri = 'YOUR_PACKAGE_ID://{yourDomain}/capacitor/YOUR_PACKAGE_ID/callback';

        const LogoutButton: React.FC = () => {
          const { logout } = useAuth0();

          const doLogout = async () => {
            await logout({
              logoutParams: {
                returnTo: logoutUri
              },
              async openUrl(url) {
                 // Redirect using Capacitor's Browser plugin
                await Browser.open({
                  url,
                  windowName: "_self"
                });
              }
            });
          };

          return <IonButton onClick={doLogout}>Log out</IonButton>;
        };

        export default LogoutButton;
        ```

        ```tsx app.tsx lines  theme={null}
        // Import Capacitor's app and browser plugins, giving us access to `addListener` and `appUrlOpen`,
        // as well as the bits needed for Auth0 and React
        import { App as CapApp } from '@capacitor/app';
        import { Browser } from '@capacitor/browser';
        import { useEffect } from 'react';
        import { useAuth0 } from '@auth0/auth0-react';

        // ...

        const App: React.FC = () => {
          // Get the callback handler from the Auth0 React hook
          const { handleRedirectCallback } = useAuth0();

          useEffect(() => {
            // Handle the 'appUrlOpen' event and call `handleRedirectCallback`
            CapApp.addListener('appUrlOpen', async ({ url }) => {
              if (url.includes('state') && (url.includes('code') || url.includes('error'))) {
                await handleRedirectCallback(url);
              }
              // No-op on Android
              await Browser.close();
            });
          }, [handleRedirectCallback]);

          // ..
        };// Import Capacitor's app and browser plugins, giving us access to `addListener` and `appUrlOpen`,
        // as well as the bits needed for Auth0 and React
        import { App as CapApp } from '@capacitor/app';
        import { Browser } from '@capacitor/browser';
        import { useEffect } from 'react';
        import { useAuth0 } from '@auth0/auth0-react';

        // ...

        const App: React.FC = () => {
          // Get the callback handler from the Auth0 React hook
          const { handleRedirectCallback } = useAuth0();

          useEffect(() => {
            // Handle the 'appUrlOpen' event and call `handleRedirectCallback`
            CapApp.addListener('appUrlOpen', async ({ url }) => {
              if (url.includes('state') && (url.includes('code') || url.includes('error'))) {
                await handleRedirectCallback(url);
              }
              // No-op on Android
              await Browser.close();
            });
          }, [handleRedirectCallback]);

          // ..
        };
        ```
      </AuthCodeGroup>
    </SideMenuSectionItem>
  </SideMenu>
</Recipe>
