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

> Esta guía muestra cómo integrar Auth0 con una aplicación Laravel 9 o 10 nueva (o existente).

# Agrega autorización a tu aplicación Laravel

export const QuickstartButtons = ({githubLink}) => {
  const text = {
    viewOnGithub: "Ver en GitHub",
    loginAndDownload: "Descargar ejemplo"
  };
  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("No se pudo analizar la URL de GitHub:", url);
      return null;
    } catch (error) {
      console.error("Error al analizar la URL de GitHub:", error);
      return null;
    }
  };
  const handleDownload = async () => {
    const params = parseGithubUrl(githubLink);
    if (!params) {
      console.error("Formato de URL de GitHub no válido");
      return;
    }
    try {
      await window.Auth0DocsUI?.getSample(params);
    } catch (error) {
      console.error("No se pudo descargar el ejemplo:", 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)}>Guardar</Button>
          <Button variant="outline" onClick={onCancel}>
            Cancelar
          </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">Selecciona tu aplicación</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="URLs de callback" placeholder="http://localhost:3000" value={callbacks} onChange={setCallbacks} />
          <Input id="logout" name="allowed_logout_urls" label="URLs de cierre de sesión" placeholder="http://localhost:3000" value={logouts} onChange={setLogouts} />
          <Input id="origins" name="web_origins" label="Orígenes web permitidos" placeholder="http://localhost:3000" value={origins} onChange={setOrigins} />

          <div className="flex gap-3 pt-2">
            <Button type="submit">Guardar</Button>
            <Button variant="outline" type="button" onClick={onCancel}>
              Cancelar
            </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: "Aplicación predeterminada"
      }];
      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 || "Sin título"
        }];
        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">Crear una nueva aplicación</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">Integrar con una aplicación existente</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">Ver una aplicación de ejemplo</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="Nombre de la aplicación" placeholder="Mi aplicación" value={name} onChange={setName} />
          <p className="text-sm text-zinc-500">Puedes cambiarlo más adelante en la configuración de la aplicación.</p>
          <div className="flex gap-3">
            <Button onClick={() => onSave(name)}>Guardar</Button>
            <Button variant="outline" onClick={onCancel}>
              Cancelar
            </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">Selecciona tu aplicación</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="URLs de callback" placeholder="http://localhost:3000" value={callbacks} onChange={setCallbacks} />
            <Input id="logout" name="allowed_logout_urls" label="URLs de cierre de sesión" placeholder="http://localhost:3000" value={logouts} onChange={setLogouts} />
            <Input id="origins" name="web_origins" label="Orígenes web permitidos" placeholder="http://localhost:3000" value={origins} onChange={setOrigins} />

            <div className="flex gap-3 pt-2">
              <Button type="submit">Guardar</Button>
              <Button variant="outline" type="button" onClick={onCancel}>
                Cancelar
              </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="Regístrate para obtener una cuenta de Auth0" style={{
      width: "250px",
      height: "250px"
    }} />
        <span className="text-center" style={{
      width: "400px"
    }}>
          Regístrate para obtener una{" "}
          <a href="https://auth0.com/signup" target="_blank" rel="noopener noreferrer">
            cuenta de Auth0
          </a>{" "}
          o{" "}
          <span className="font-semibold text-primary dark:text-white cursor-pointer" onClick={() => console.log("log in")}>
            inicia sesión
          </span>{" "}
          en tu cuenta existente para integrarte directamente con tu propio 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"
    }}>
          Regístrate
        </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/laravel/tree/7.x/sample" />

export const sections = [{
  id: "laravel-installation",
  title: "Instalación de Laravel"
}, {
  id: "sdk-installation",
  title: "Instalación del SDK"
}, {
  id: "sdk-configuration",
  title: "Configuración del SDK"
}, {
  id: "access-control",
  title: "Control de acceso"
}, {
  id: "token-information",
  title: "Información sobre el token"
}, {
  id: "retrieve-user-information",
  title: "Obtener información del usuario"
}, {
  id: "run-the-application",
  title: "Ejecutar la aplicación"
}, {
  id: "retrieve-a-test-token",
  title: "Obtener un token de prueba"
}];

<Recipe>
  <Content>
    [Auth0's Laravel SDK](https://github.com/auth0/laravel-auth0)
    te permite agregar rápidamente autorización basada en tokens y control de acceso a rutas en tu aplicación Laravel. Esta guía
    muestra cómo integrar Auth0 con una aplicación [Laravel 9
    o 10](https://github.com/auth0/laravel-auth0#support-policy) nueva (o existente).

    **Las aplicaciones backend se diferencian de las aplicaciones web tradicionales en que no gestionan la autenticación de usuarios ni cuentan con una interfaz de usuario. Proporcionan una API con la que otras aplicaciones pueden interactuar. Aceptan **[tokens de acceso](https://auth0.com/docs/secure/tokens/access-tokens)** desde
    los encabezados **`Authorization`** de las solicitudes para controlar el acceso a las rutas.**

    Por lo general, se crean aplicaciones front-end independientes para interactuar con este tipo de backends. Estas pueden ser desde [aplicaciones de página única](https://auth0.com/docs/quickstart/spa) hasta [aplicaciones nativas o móviles](https://auth0.com/docs/quickstart/native) (¡y Auth0 también ofrece SDKs para todas ellas!)

    Cuando los usuarios necesitan interactuar con tu aplicación backend, primero se autentican con Auth0 a través de la aplicación
    frontend. Luego, la aplicación frontend obtiene un token de acceso de Auth0, que puede utilizar para realizar solicitudes
    a tu aplicación backend en nombre del usuario.

    Como su nombre indica, los [tokens de
    acceso](https://auth0.com/docs/secure/tokens/access-tokens) están diseñados para gestionar el control de acceso (autorización) y no contienen información sobre
    el usuario. **Las aplicaciones de backend trabajan exclusivamente con tokens de acceso.** Puedes recuperar información sobre el
    usuario que creó el token mediante la [API de
    Management](https://auth0.com/docs/api/management/v2), como se mostrará más adelante.

    <Section id={sections[0].id} title={sections[0].title} stepNumber="1">
      **Si aún no tiene configurada una aplicación de Laravel**, abra una terminal en un directorio adecuado para un nuevo
      proyecto y ejecute el siguiente comando:

      ```bash lines wrap theme={null}
      composer create-project --prefer-dist laravel/laravel auth0-laravel-api ^9.0
      ```

      Todos los comandos de esta guía asumen que los ejecuta desde el directorio raíz de su proyecto de Laravel, por lo que
      debe ir al directorio del nuevo proyecto con `cd`:

      ```bash lines theme={null}
      cd auth0-laravel-api
      ```
    </Section>

    <Section id={sections[1].id} title={sections[1].title} stepNumber="2">
      Ejecute el siguiente comando en el directorio de su proyecto para instalar el [Auth0 Laravel SDK](https://github.com/auth0/laravel-auth0):

      ```bash lines theme={null}
      composer require auth0/login:^7.8 --update-with-all-dependencies
      ```

      Luego, genere un archivo de configuración del SDK para su aplicación:

      ```bash lines theme={null}
      php artisan vendor:publish --tag auth0
      ```
    </Section>

    <Section id={sections[2].id} title={sections[2].title} stepNumber="3">
      Ejecute el siguiente comando desde el directorio de su proyecto para descargar la [CLI de Auth0](https://github.com/auth0/auth0-cli):

      ```bash lines wrap theme={null}
      curl -sSfL https://raw.githubusercontent.com/auth0/auth0-cli/main/install.sh | sh -s -- -b .
      ```

      Luego, autentica la CLI con tu cuenta de Auth0 y elige "como usuario" cuando se te indique:

      ```bash lines theme={null}
      ./auth0 login
      ```

      A continuación, cree una aplicación nueva con Auth0:

      ```bash lines theme={null}
      ./auth0 apps create \
        --name "My Laravel Backend" \
        --type "regular" \
        --auth-method "post" \
        --callbacks "http://localhost:8000/callback" \
        --logout-urls "http://localhost:8000" \
        --reveal-secrets \
        --no-input \
        --json > .auth0.app.json
      ```

      También debes crear una API nueva:

      ```bash lines theme={null}
      ./auth0 apis create \
        --name "My Laravel Backend API" \
        --identifier "https://github.com/auth0/laravel-auth0" \
        --offline-access \
        --no-input \
        --json > .auth0.api.json
      ```

      Esto genera dos archivos en el directorio de tu proyecto que configuran el SDK.

      Como estos archivos contienen credenciales, es importante tratarlos como información confidencial. Debes asegurarte de no
      incluirlos en el control de versiones. Si usas Git, debes agregarlos a tu archivo `.gitignore`:

      ```bash lines theme={null}
      echo ".auth0.*.json" >> .gitignore
      ```
    </Section>

    <Section id={sections[3].id} title={sections[3].title} stepNumber="4">
      El SDK registra automáticamente su guard de autorización en su aplicación Laravel para usarlo con el
      middleware `api`, que Laravel aplica de forma predeterminada a todas las rutas del archivo
      `routes/api.php` de su aplicación.

      <Warning>
        Para que el SDK funcione como se espera sin configuración adicional, **debe definir sus rutas en
        el archivo **`routes/api.php`**.**
      </Warning>

      Puede usar el guard de autorización del SDK de Auth0 para restringir el acceso a las rutas de su aplicación.

      Para rechazar solicitudes que no contengan un token de acceso válido en el encabezado `Authorization`, puede usar
      el middleware `auth` de Laravel:

      ```php lines theme={null}
      Route::get('/private', function () {
      return response()->json([
      'message' => 'Your token is valid; you are authorized.',
      ]);
      })->middleware('auth');
      ```

      También puede exigir que el token proporcionado tenga [permisos](https://auth0.com/docs/manage-users/access-control/rbac) específicos al combinar esto
      con el middleware `can` de Laravel:

      ```php lines theme={null}
      Route::get('/scope', function () {
      return response()->json([
      'message' => 'Your token is valid and has the read:messages permission; you are authorized.',
      ]);
      })->middleware('auth')->can('read:messages');
      ```
    </Section>

    <Section id={sections[4].id} title={sections[4].title} stepNumber="5">
      La información sobre el token de acceso proporcionado puede obtenerse mediante la fachada `Auth` de Laravel o la
      función auxiliar `auth()`.

      Por ejemplo, para obtener el identificador y la dirección de correo electrónico del usuario:

      ```php lines theme={null}
      Route::get('/', function () {
      if (! auth()->check()) {
      return response()->json([
      'message' => 'You did not provide a valid token.',
      ]);
      }
      return response()->json([
      'message' => 'Your token is valid; you are authorized.',
      'id' => auth()->id(),
      'token' => auth()?->user()?->getAttributes(),
      ]);
      });
      ```
    </Section>

    <Section id={sections[5].id} title={sections[5].title} stepNumber="6">
      Puede obtener información sobre el usuario que creó el token de acceso desde Auth0 mediante la [Management API](https://github.com/auth0/laravel-auth0/blob/main/docs/Management.md). El SDK proporciona un contenedor práctico para esta API,
      accesible mediante el método `management()` del SDK.

      **Antes de realizar llamadas a la Management API, debe habilitar su aplicación para que se comunique con la
      Management API.** Esto puede hacerse desde la [página API del Auth0 Dashboard](https://manage.auth0.com/#/apis/), eligiendo `Auth0 Management API` y
      seleccionando la pestaña 'Aplicaciones de máquina a máquina'. Autorice su aplicación de Laravel y, a continuación, haga clic en la flecha
      desplegable para elegir los alcances que desea conceder.

      Para el siguiente ejemplo, debe conceder el alcance `read:users`. Puede encontrar una lista de endpoints de API y los
      alcances requeridos en [la documentación de la Management
      API](https://auth0.com/docs/api/management/v2).

      ```php lines theme={null}
      use Auth0\Laravel\Facade\Auth0;
      Route::get('/me', function () {
      $user = auth()->id();
      $profile = cache()->get($user);
      if (null === $profile) {
      $endpoint = Auth0::management()->users();
      $profile = $endpoint->get($user);
      $profile = Auth0::json($profile);
      cache()->put($user, $profile, 120);
      }
      $name = $profile['name'] ?? 'Unknown';
      $email = $profile['email'] ?? 'Unknown';
      return response()->json([
      'name' => $name,
      'email' => $email,
      ]);
      })->middleware('auth');
      ```

      <Info>
        **Debe almacenar en caché la información del usuario en su aplicación solo durante períodos breves.** Esto reduce la cantidad
        de solicitudes que su aplicación realiza a Auth0 y mejora el rendimiento. Debe evitar almacenar información del usuario
        en su aplicación durante períodos prolongados, ya que esto puede dar lugar a datos desactualizados. También debe evitar
        almacenar en bases de datos persistentes información del usuario que exceda su identificador.
      </Info>
    </Section>

    <Section id={sections[6].id} title={sections[6].title} stepNumber="7">
      Ahora ya puede iniciar su aplicación Laravel para que pueda aceptar solicitudes:

      ```bash lines theme={null}
      php artisan serve
      ```
    </Section>

    <Section id={sections[7].id} title={sections[7].title} stepNumber="8">
      Puede obtener más información sobre [cómo obtener tokens de acceso aquí](https://auth0.com/docs/secure/tokens/access-tokens/get-access-tokens). Sin embargo, para esta guía de inicio rápido, puede simplemente usar un token de acceso
      de [la vista de "prueba" en la configuración de su API](https://manage.auth0.com/#/apis).

      <Info>
        La ruta `/me` que creamos anteriormente no funcionará con un token de prueba, ya que no hay ningún usuario real
        asociado.
      </Info>

      <Note>
        ##### Punto de control

        Abra una shell e intente enviar solicitudes a su aplicación.

        Comience solicitando la ruta pública:

        `curl --request GET \ --url http://localhost:8000/api \ --header 'Accept: application/json'`

        A continuación, use su token de acceso en un encabezado `Authorization` para solicitar una ruta protegida:

        `curl --request GET \ --url http://localhost:8000/api/private \ --header 'Accept: application/json' \ --header 'Authorization: Bearer YOUR_ACCESS_TOKEN'`

        Por último, intente solicitar la ruta protegida por scope, que solo funcionará si al token de acceso se le ha concedido el
        scope `read:messages`:

        `curl --request GET \ --url http://localhost:8000/api/scope \ --header 'Accept: application/json' \ --header 'Authorization: Bearer YOUR_ACCESS_TOKEN'`
      </Note>

      ### Lectura adicional

      * [Repositorios y modelos de usuario](https://github.com/auth0/laravel-auth0/blob/main/docs/Users.md) amplía el SDK de Auth0 para Laravel para usar modelos de usuario
        personalizados, y explica cómo almacenar y recuperar usuarios de una base de datos.
      * [Conexión de eventos](https://github.com/auth0/laravel-auth0/blob/main/docs/Events.md) explica cómo escuchar los eventos generados por el SDK de Auth0 para Laravel
        para personalizar por completo el comportamiento de su integración.
      * La compatibilidad con [Management API](https://github.com/auth0/laravel-auth0/blob/main/docs/Management.md) está integrada en el SDK de Auth0 para Laravel, lo que le permite
        interactuar con la Management API desde su aplicación Laravel.
    </Section>

    ## Próximos pasos

    ¡Excelente trabajo! Si llegaste hasta aquí, ya deberías tener el inicio de sesión, el cierre de sesión y la información del perfil de usuario funcionando en tu aplicación.

    Con esto concluye nuestro tutorial de inicio rápido, pero hay mucho más por explorar. Para saber más sobre lo que puedes hacer con Auth0, consulta:

    * [Auth0 Dashboard](https://manage.auth0.com/dashboard/us/dev-gja8kxz4ndtex3rq) - Aprenda a configurar y administrar su inquilino y sus aplicaciones de Auth0
    * [SDK laravel-auth0](https://github.com/auth0/laravel-auth0) - Explora más a fondo el SDK utilizado en este tutorial
    * [Auth0 Marketplace](https://marketplace.auth0.com/) - Descubra las integraciones que puede habilitar para ampliar la funcionalidad de Auth0
  </Content>

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

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

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

    <SideMenuSectionItem id={sections[3].id}>
      ```php routes/api.php lines highlight={6-16} theme={null}
      <?php

      use Auth0\Laravel\Facade\Auth0;
      use Illuminate\Support\Facades\Route;

      Route::get('/private', function () {
        return response()->json([
          'message' => 'Your token is valid; you are authorized.',
        ]);
      })->middleware('auth');

      Route::get('/scope', function () {
          return response()->json([
            'message' => 'Your token is valid and has the `read:messages` permission; you are authorized.',
          ]);
      })->middleware('auth')->can('read:messages');

      Route::get('/', function () {
        if (! auth()->check()) {
          return response()->json([
            'message' => 'You did not provide a valid token.',
          ]);
        }

        return response()->json([
          'message' => 'Your token is valid; you are authorized.',
          'id' => auth()->id(),
          'token' => auth()?->user()?->getAttributes(),
        ]);
      });

      Route::get('/me', function () {
        $user = auth()->id();
        $profile = cache()->get($user);

        if (null === $profile) {
          $endpoint = Auth0::management()->users();
          $profile = $endpoint->get($user);
          $profile = Auth0::json($profile);

          cache()->put($user, $profile, 120);
        }

        $name = $profile['name'] ?? 'Unknown';
        $email = $profile['email'] ?? 'Unknown';

        return response()->json([
          'name' => $name,
          'email' => $email,
        ]);
      })->middleware('auth');
      ```
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[4].id}>
      ```php routes/api.php lines highlight={18-30} theme={null}
      <?php

      use Auth0\Laravel\Facade\Auth0;
      use Illuminate\Support\Facades\Route;

      Route::get('/private', function () {
        return response()->json([
          'message' => 'Your token is valid; you are authorized.',
        ]);
      })->middleware('auth');

      Route::get('/scope', function () {
          return response()->json([
            'message' => 'Your token is valid and has the `read:messages` permission; you are authorized.',
          ]);
      })->middleware('auth')->can('read:messages');

      Route::get('/', function () {
        if (! auth()->check()) {
          return response()->json([
            'message' => 'You did not provide a valid token.',
          ]);
        }

        return response()->json([
          'message' => 'Your token is valid; you are authorized.',
          'id' => auth()->id(),
          'token' => auth()?->user()?->getAttributes(),
        ]);
      });

      Route::get('/me', function () {
        $user = auth()->id();
        $profile = cache()->get($user);

        if (null === $profile) {
          $endpoint = Auth0::management()->users();
          $profile = $endpoint->get($user);
          $profile = Auth0::json($profile);

          cache()->put($user, $profile, 120);
        }

        $name = $profile['name'] ?? 'Unknown';
        $email = $profile['email'] ?? 'Unknown';

        return response()->json([
          'name' => $name,
          'email' => $email,
        ]);
      })->middleware('auth');
      ```
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[5].id}>
      ```php routes/api.php lines highlight={32-51} theme={null}
      <?php

      use Auth0\Laravel\Facade\Auth0;
      use Illuminate\Support\Facades\Route;

      Route::get('/private', function () {
        return response()->json([
          'message' => 'Your token is valid; you are authorized.',
        ]);
      })->middleware('auth');

      Route::get('/scope', function () {
          return response()->json([
            'message' => 'Your token is valid and has the `read:messages` permission; you are authorized.',
          ]);
      })->middleware('auth')->can('read:messages');

      Route::get('/', function () {
        if (! auth()->check()) {
          return response()->json([
            'message' => 'You did not provide a valid token.',
          ]);
        }

        return response()->json([
          'message' => 'Your token is valid; you are authorized.',
          'id' => auth()->id(),
          'token' => auth()?->user()?->getAttributes(),
        ]);
      });

      Route::get('/me', function () {
        $user = auth()->id();
        $profile = cache()->get($user);

        if (null === $profile) {
          $endpoint = Auth0::management()->users();
          $profile = $endpoint->get($user);
          $profile = Auth0::json($profile);

          cache()->put($user, $profile, 120);
        }

        $name = $profile['name'] ?? 'Unknown';
        $email = $profile['email'] ?? 'Unknown';

        return response()->json([
          'name' => $name,
          'email' => $email,
        ]);
      })->middleware('auth');
      ```
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[6].id}>
      <SignUpForm />
    </SideMenuSectionItem>

    <SideMenuSectionItem id={sections[7].id}>
      <SignUpForm />
    </SideMenuSectionItem>
  </SideMenu>
</Recipe>
