> ## 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.

# Ajouter la fonctionnalité Login à votre application Ionic Vue avec Capacitor

> Ce guide explique comment intégrer Auth0 à une application Ionic Vue et Capacitor à l’aide du SDK Auth0 pour Vue.

export const HowToSchema = () => <script type="application/ld+json">
    {'{"@context":"https://schema.org","@type":"HowTo"}'}
  </script>;

export const CreateInteractiveApp = ({placeholderText = "Auth0", appType = "regular_web", allowedCallbackUrls = ["localhost:3000"], allowedLogoutUrls = ["localhost:3000"], allowedOriginUrls = ["localhost:3000"]}) => {
  const [isAuthenticated, setIsAuthenticated] = useState(false);
  const [storeReady, setStoreReady] = useState(false);
  const [displayForm, setDisplayForm] = useState(true);
  useEffect(() => {
    const init = () => setStoreReady(true);
    if (window.rootStore) {
      window.rootStore.clientStore.setSelectedClient(null);
      window.rootStore.clientStore.setSelectedClientSecret(undefined);
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
    };
  }, []);
  useEffect(() => {
    if (!storeReady) return;
    const disposer = autorun(() => {
      const rootStore = window.rootStore;
      setIsAuthenticated(rootStore.sessionStore.isAuthenticated);
    });
    return () => {
      disposer();
    };
  }, [storeReady]);
  if (!storeReady || typeof window === "undefined" || !displayForm) {
    return <></>;
  }
  const login = () => {
    const baseUrl = window.rootStore.config.apiBaseUrl;
    const returnTo = encodeURIComponent(window.location.href);
    window.location.href = `${baseUrl}/auth/user/login?returnTo=${returnTo}`;
  };
  const Card = ({className = "", children}) => {
    return <div className={`
          flex border rounded-2xl
          border-gray-950/10 dark:border-white/10
          py-3.5 px-4 gap-2
          text-sm text-gray-900 dark:text-gray-200
          ${className}
        `}>
        {children}
      </div>;
  };
  const Button = ({children, ...props}) => {
    return <button className="bg-[--button-primary] text-[--foreground-inverse] px-[1.125rem] py-1.5 rounded-lg font-medium" {...props}>
        {children}
      </button>;
  };
  const CreateApplicationForm = () => {
    const [name, setName] = useState("");
    const [isLoading, setIsLoading] = useState(false);
    const [error, setError] = useState("");
    const handleSubmit = async () => {
      if (!name.trim()) {
        setError("Le nom de l'application est requis");
        return;
      }
      setIsLoading(true);
      setError(null);
      try {
        await window.rootStore.clientStore.createClient({
          name: name.trim(),
          app_type: appType,
          callbacks: allowedCallbackUrls,
          allowed_logout_urls: allowedLogoutUrls,
          web_origins: allowedOriginUrls,
          client_metadata: {
            created_by: "quickstart-docs-app-creation-component"
          }
        });
        setDisplayForm(false);
      } catch (err) {
        console.error("Erreur lors de la création de l'application :", err);
        const errorMessage = err instanceof Error ? err.message : "Échec de la création de l'application";
        setError(errorMessage);
      } finally {
        setIsLoading(false);
      }
    };
    return <Card className="flex-col items-start p-4 gap-3.75">
        <span className="font-medium text-gray-900 dark:text-gray-200">Créer une application Auth0</span>
        <div className="w-full flex gap-2">
          <input id="app-name" name={name} className="
              w-full max-w-[448px] h-11 py-2 px-4 
              border rounded-lg border-gray-950/10 dark:border-white/10 
              text-gray-900 dark:text-gray-200
              focus:outline-none dark:focus:outline-none
            " placeholder={`Mon application ${placeholderText}`} value={name} onChange={e => setName(e.target.value)} />
          <Button onClick={handleSubmit}>{isLoading ? "Création en cours..." : "Créer"}</Button>
        </div>
        {error && <p className="text-red-500">{error}</p>}
      </Card>;
  };
  const SignInForm = () => {
    return <Card className="items-center">
        <Button onClick={login}>Se connecter</Button> <span>pour créer l'application</span>
      </Card>;
  };
  return isAuthenticated ? <CreateApplicationForm /> : <SignInForm />;
};

export const AuthCodeBlock = ({filename, icon, language, highlight, children}) => {
  const [displayText, setDisplayText] = useState(children);
  const [copyText, setCopyText] = useState(children);
  const wrapperRef = React.useRef(null);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      if (!window.autorun || !window.rootStore) {
        return;
      }
      unsubscribe = window.autorun(() => {
        let processedChildrenForDisplay = children;
        let processedChildrenForCopy = children;
        for (const [key, value] of window.rootStore.variableStore.values.entries()) {
          const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
          let displayValue = value;
          if (key === "{yourClientSecret}" && value !== "{yourClientSecret}") {
            displayValue = value.substring(0, 3) + "*****MASKED*****";
          }
          processedChildrenForDisplay = processedChildrenForDisplay.replaceAll(new RegExp(escapedKey, "g"), displayValue);
          processedChildrenForCopy = processedChildrenForCopy.replaceAll(new RegExp(escapedKey, "g"), value);
        }
        setDisplayText(processedChildrenForDisplay);
        setCopyText(processedChildrenForCopy);
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  useEffect(() => {
    if (!wrapperRef.current) return;
    const originalWriteText = navigator.clipboard.writeText.bind(navigator.clipboard);
    let isOverriding = false;
    const handleClick = e => {
      const button = e.target.closest('[data-testid="copy-code-button"]');
      if (!button || !wrapperRef.current.contains(button)) return;
      isOverriding = true;
      navigator.clipboard.writeText = text => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
          return originalWriteText(copyText);
        }
        return originalWriteText(text);
      };
      setTimeout(() => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
        }
      }, 100);
    };
    const wrapper = wrapperRef.current;
    wrapper.addEventListener('click', handleClick, true);
    return () => {
      wrapper.removeEventListener('click', handleClick, true);
      if (navigator.clipboard.writeText !== originalWriteText) {
        navigator.clipboard.writeText = originalWriteText;
      }
    };
  }, [copyText]);
  return <div ref={wrapperRef}>
      <CodeBlock filename={filename} icon={icon} language={language} lines highlight={highlight}>
        {displayText}
      </CodeBlock>
    </div>;
};

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>;
};

<HowToSchema />

<Accordion title="Utiliser l’IA pour intégrer Auth0" icon="microchip-ai" iconType="solid" defaultOpen>
  Si vous utilisez un assistant de programmation IA comme Claude Code, Cursor ou GitHub Copilot, vous pouvez ajouter automatiquement l’authentification Auth0 en quelques minutes à l’aide des [agent skills](https://agentskills.io/home).
  Commencez par installer les agent skills d’Auth0 :

  ```bash theme={null}
  npx skills add auth0/agent-skills --skill auth0-quickstart --skill auth0-ionic-vue
  ```

  Ensuite, demandez à votre assistant IA :

  ```text theme={null}
  Add Auth0 authentication to my Ionic Vue app
  ```

  Votre assistant IA créera automatiquement votre application Auth0, récupérera les identifiants, installera le SDK Auth0 Vue et les plugins Capacitor, configurera les liens profonds et mettra en œuvre des flux de connexion et de déconnexion avec intégration au navigateur natif. Pour en savoir plus, consultez [Auth0 agent skills](/fr-CA/docs/quickstart/agent-skills).
</Accordion>

<div id="get-started">
  ## Pour commencer
</div>

Ce guide de démarrage rapide montre comment ajouter l’authentification Auth0 à une application Ionic Vue exécutée sur iOS et Android avec Capacitor. Vous créerez une application mobile sécurisée avec des fonctionnalités de connexion, de déconnexion et de profil utilisateur à l’aide du SDK Auth0 pour Vue et des plugiciels de navigateur natifs de Capacitor.

<Steps>
  <Step title="Créer un nouveau projet" stepNumber={1}>
    Créez un projet Ionic Vue avec Capacitor

    ```shellscript theme={null}
    npx ionic start auth0-ionic-vue blank --type=vue --capacitor
    ```

    Ouvrez le projet

    ```shellscript theme={null}
    cd auth0-ionic-vue
    ```

    <Warning>
      Assurez-vous d’utiliser le package `@ionic/cli` (et non le package `ionic`, maintenant obsolète). Si des erreurs liées à `--npm-client` s’affichent pendant la création du projet, mettez à jour votre CLI :

      ```shellscript theme={null}
      npm uninstall -g ionic
      npm i -g @ionic/cli
      ```
    </Warning>
  </Step>

  <Step title="Installez le SDK Vue d’Auth0 et les plugins Capacitor" stepNumber={2}>
    ```shellscript theme={null}
    npm install @auth0/auth0-vue @capacitor/browser @capacitor/app
    ```

    <Info>
      **[`@capacitor/browser`](https://capacitorjs.com/docs/apis/browser)** ouvre la page Universal Login d’Auth0 dans le navigateur système de l’appareil (SFSafariViewController sur iOS, Chrome Custom Tabs sur Android) pour une authentification sécurisée.

      **[`@capacitor/app`](https://capacitorjs.com/docs/apis/app)** écoute les événements de lien profond afin que votre application puisse gérer la redirection OAuth lorsqu’Auth0 redirige l’utilisateur après la connexion.
    </Info>
  </Step>

  <Step title="Configurez votre application Auth0" stepNumber={3}>
    La prochaine étape consiste à créer une nouvelle application dans votre locataire Auth0. Les applications Ionic Capacitor utilisent le type d’application **Native** avec des URL de rappel basées sur un schéma d’URL personnalisé.

    Vous avez trois options pour configurer votre application Auth0 : utiliser l’outil de configuration rapide (recommandé), exécuter une commande CLI ou effectuer la configuration manuellement dans l’Auth0 Dashboard :

    <Tabs>
      <Tab title="Configuration rapide (recommandée)">
        Créez une application Auth0 **Native** et obtenez vos identifiants.

        <CreateInteractiveApp placeholderText="Ionic Vue" appType="native" allowedCallbackUrls={[]} allowedLogoutUrls={[]} allowedOriginUrls={["capacitor://localhost", "http://localhost"]} />

        Après avoir créé votre application, notez les valeurs **Domain** et **Client ID** pour l’étape suivante.

        <Note>
          Vous devrez aussi configurer les URL de rappel et de déconnexion dans le Dashboard. Consultez la configuration des URL ci-dessous.
        </Note>
      </Tab>

      <Tab title="CLI">
        Exécutez les commandes suivantes à la racine de votre projet pour créer une application Auth0 :

        <CodeGroup>
          ```shellscript Mac theme={null}
          # Installer Auth0 CLI (si ce n'est pas déjà fait)
          brew tap auth0/auth0-cli && brew install auth0

          # Ouvrir une session et créer une application Native
          auth0 login && auth0 apps create \
            -n "My Ionic Vue App" \
            -t native \
            -o "capacitor://localhost,http://localhost" \
            --no-input
          ```

          ```powershell Windows theme={null}
          # Installer Auth0 CLI (si ce n'est pas déjà fait)
          scoop bucket add auth0 https://github.com/auth0/scoop-auth0-cli.git
          scoop install auth0

          # Ouvrir une session et créer une application Native
          auth0 login; auth0 apps create `
            -n "My Ionic Vue App" `
            -t native `
            -o "capacitor://localhost,http://localhost" `
            --no-input
          ```
        </CodeGroup>

        <Note>
          Cette commande va :

          1. Vous authentifier auprès d’Auth0 (et vous inviter à ouvrir une session au besoin)
          2. Créer une application **Native** avec les origines autorisées configurées
          3. Afficher les valeurs **Domain** et **Client ID** à utiliser dans votre projet

          Vous devrez tout de même configurer les URL de rappel et de déconnexion dans le Dashboard. Voir ci-dessous.
        </Note>
      </Tab>

      <Tab title="Dashboard">
        1. Accédez à l’[Auth0 Dashboard](https://manage.auth0.com/dashboard/)
        2. Cliquez sur **Applications** > **Applications** > **Create Application**
        3. Saisissez un nom pour votre application (par exemple, `Ionic Vue App`), sélectionnez **Native** comme type d’application, puis cliquez sur **Create**
        4. Ouvrez l’onglet **Settings** et notez les valeurs **Domain** et **Client ID**

        <Info>
          Dans ce guide, `YOUR_PACKAGE_ID` correspond à l’ID de package de votre application. Vous pouvez le trouver et le configurer dans le champ `appId` de votre fichier `capacitor.config.ts`. Consultez le [schéma de configuration de Capacitor](https://capacitorjs.com/docs/config#schema) pour en savoir plus.
        </Info>

        Configurez les URL suivantes dans l’onglet **Settings** de la page des détails de votre application :

        **Allowed Callback URLs:**

        ```text theme={null}
        YOUR_PACKAGE_ID://{yourDomain}/capacitor/YOUR_PACKAGE_ID/callback
        ```

        **Allowed Logout URLs:**

        ```text theme={null}
        YOUR_PACKAGE_ID://{yourDomain}/capacitor/YOUR_PACKAGE_ID/callback
        ```

        **Allowed Origins:**

        ```text theme={null}
        capacitor://localhost, http://localhost
        ```

        <Info>
          **Allowed Callback URLs** constituent une mesure de sécurité essentielle pour garantir que les utilisateurs sont redirigés de façon sécuritaire vers votre application après l’authentification. Sans URL correspondante, le processus de connexion échouera et les utilisateurs verront une page d’erreur Auth0 au lieu d’accéder à votre application.

          **Allowed Logout URLs** sont essentielles pour offrir une expérience fluide lors de la déconnexion. Sans URL correspondante, les utilisateurs ne seront pas redirigés vers votre application après la déconnexion et resteront plutôt sur une page Auth0 générique.

          **Allowed Origins** doivent inclure `capacitor://localhost` (iOS) et `http://localhost` (Android) pour les requêtes d’application native vers Auth0.
        </Info>
      </Tab>
    </Tabs>

    <Tip>
      Si vous avez utilisé la **Configuration rapide** ou le **CLI**, ouvrez l’onglet **Settings** de votre application dans l’[Auth0 Dashboard](https://manage.auth0.com/#/applications) pour configurer les URL de rappel et de déconnexion indiquées dans l’onglet Dashboard ci-dessus.
    </Tip>
  </Step>

  <Step title="Configurer le plugiciel Auth0" stepNumber={4}>
    ```typescript src/main.ts {5,6,8,9,14,15,16,17,18,19,20,21,22,23} lines theme={null}
    import { createApp } from 'vue'
    import App from './App.vue'
    import router from './router'
    import { IonicVue } from '@ionic/vue'
    import { createAuth0 } from '@auth0/auth0-vue'
    import config from '../capacitor.config'

    // Construire l'URL de callback à partir de l'identifiant de paquet de votre application
    const redirect_uri = `${config.appId}://{yourDomain}/capacitor/${config.appId}/callback`

    const app = createApp(App)
      .use(IonicVue)
      .use(router)

    app.use(
      createAuth0({
        domain: '{yourDomain}',
        clientId: '{yourClientId}',
        useRefreshTokens: true,
        useRefreshTokensFallback: false,
        authorizationParams: {
          redirect_uri,
        },
      })
    )

    router.isReady().then(() => {
      app.mount('#app')
    })
    ```

    <Info>
      * **`useRefreshTokens: true`** — Les navigateurs mobiles bloquent les cookies tiers; l’authentification silencieuse basée sur des iframes ne fonctionne donc pas. Les jetons d’actualisation appellent directement le point de terminaison `/oauth/token`.
      * **`useRefreshTokensFallback: false`** — Empêche le SDK de tenter le mécanisme de repli basé sur une iframe, qui n’est pas disponible sur mobile.
      * **`router.isReady().then(...)`** — Garantit que Vue Router est entièrement initialisé avant que le SDK ne traite le callback OAuth, ce qui évite les conditions de concurrence.
    </Info>

    <Warning>
      Pour conserver l’authentification après la fermeture et la réouverture de l’application, vous pouvez définir `cacheLocation` à `localstorage`, mais veuillez prendre connaissance des [risques liés au stockage des jetons dans localstorage](https://auth0.com/docs/libraries/auth0-single-page-app-sdk#change-storage-options). De plus, `localstorage` doit être considéré comme **transitoire** dans les applications Capacitor, car les données pourraient être récupérées de façon inattendue. Veuillez consulter les [directives sur le stockage dans la documentation de Capacitor](https://capacitorjs.com/docs/guides/storage#why-cant-i-just-use-localstorage-or-indexeddb).
    </Warning>
  </Step>

  <Step title="Créer des composants d’authentification" stepNumber={5}>
    Créer des fichiers de composants

    <CodeGroup>
      ```shellscript Mac/Linux theme={null}
      mkdir -p src/components && touch src/components/LoginButton.vue && touch src/components/LogoutButton.vue && touch src/components/UserProfile.vue
      ```

      ```powershell Windows theme={null}
      New-Item -ItemType Directory -Force -Path src/components
      New-Item -ItemType File -Path src/components/LoginButton.vue
      New-Item -ItemType File -Path src/components/LogoutButton.vue
      New-Item -ItemType File -Path src/components/UserProfile.vue
      ```
    </CodeGroup>

    Ajoutez le code suivant aux nouveaux composants et mettez à jour les fichiers `App.vue` et `HomePage.vue` existants

    <AuthCodeGroup>
      ```vue src/components/LoginButton.vue lines theme={null}
      <template>
        <ion-button @click="login" expand="block">Log in</ion-button>
      </template>

      <script setup lang="ts">
      import { useAuth0 } from '@auth0/auth0-vue'
      import { Browser } from '@capacitor/browser'
      import { IonButton } from '@ionic/vue'

      const { loginWithRedirect } = useAuth0()

      const login = async () => {
        await loginWithRedirect({
          openUrl: (url: string) =>
            Browser.open({ url, windowName: '_self' }),
        })
      }
      </script>
      ```

      ```vue src/components/LogoutButton.vue lines theme={null}
      <template>
        <ion-button @click="onLogout" expand="block" color="danger">
          Log out
        </ion-button>
      </template>

      <script setup lang="ts">
      import { useAuth0 } from '@auth0/auth0-vue'
      import { Browser } from '@capacitor/browser'
      import { IonButton } from '@ionic/vue'
      import config from '../../capacitor.config'

      const returnTo = `${config.appId}://{yourDomain}/capacitor/${config.appId}/callback`

      const { logout } = useAuth0()

      const onLogout = async () => {
        await logout({
          logoutParams: { returnTo },
          openUrl: (url: string) =>
            Browser.open({ url, windowName: '_self' }),
        })
      }
      </script>
      ```

      ```vue src/components/UserProfile.vue expandable lines theme={null}
      <template>
        <div v-if="isLoading" class="ion-text-center">
          <p>Loading profile...</p>
        </div>
        <div v-else-if="isAuthenticated && user" class="ion-text-center">
          <ion-avatar style="margin: 0 auto; width: 80px; height: 80px;">
            <img :src="user.picture" :alt="user.name" />
          </ion-avatar>
          <h2>{{ user.name }}</h2>
          <p>{{ user.email }}</p>
        </div>
      </template>

      <script setup lang="ts">
      import { useAuth0 } from '@auth0/auth0-vue'
      import { IonAvatar } from '@ionic/vue'

      const { user, isAuthenticated, isLoading } = useAuth0()
      </script>
      ```

      ```vue src/views/HomePage.vue expandable lines theme={null}
      <template>
        <ion-page>
          <ion-header>
            <ion-toolbar>
              <ion-title>Auth0 + Ionic Vue</ion-title>
            </ion-toolbar>
          </ion-header>

          <ion-content class="ion-padding ion-text-center">
            <div v-if="isLoading">
              <ion-spinner />
              <p>Loading...</p>
            </div>

            <div v-else-if="error">
              <h2>Oops!</h2>
              <p>{{ error.message }}</p>
            </div>

            <div v-else-if="isAuthenticated">
              <div style="margin-bottom: 1rem;">
                <UserProfile />
              </div>
              <LogoutButton />
            </div>

            <div v-else>
              <h2>Welcome</h2>
              <p>Get started by signing in to your account</p>
              <LoginButton />
            </div>
          </ion-content>
        </ion-page>
      </template>

      <script setup lang="ts">
      import {
        IonPage,
        IonHeader,
        IonToolbar,
        IonTitle,
        IonContent,
        IonSpinner,
      } from '@ionic/vue'
      import { useAuth0 } from '@auth0/auth0-vue'
      import LoginButton from '../components/LoginButton.vue'
      import LogoutButton from '../components/LogoutButton.vue'
      import UserProfile from '../components/UserProfile.vue'

      const { isAuthenticated, isLoading, error } = useAuth0()
      </script>
      ```

      ```vue src/App.vue expandable lines theme={null}
      <template>
        <ion-app>
          <ion-router-outlet />
        </ion-app>
      </template>

      <script setup lang="ts">
      import { IonApp, IonRouterOutlet } from '@ionic/vue'
      import { useAuth0 } from '@auth0/auth0-vue'
      import { App as CapApp } from '@capacitor/app'
      import { Browser } from '@capacitor/browser'

      const { handleRedirectCallback } = useAuth0()

      CapApp.addListener('appUrlOpen', async ({ url }) => {
        if (url.includes('state') && (url.includes('code') || url.includes('error'))) {
          await handleRedirectCallback(url)
        }
        await Browser.close()
      })
      </script>
      ```
    </AuthCodeGroup>
  </Step>

  <Step title="Lancez votre application" stepNumber={6}>
    Commencez par tester dans le navigateur :

    ```shellscript theme={null}
    ionic serve
    ```

    <Warning>
      Lors de l’exécution dans le navigateur avec `ionic serve`, la redirection avec un schéma d’URL personnalisé ne fonctionnera pas, car les navigateurs ne peuvent pas gérer les schémas d’URL personnalisés. Pour effectuer des tests dans le navigateur, remplacez temporairement `redirect_uri` par `http://localhost:8100` dans `src/main.ts`, puis ajoutez `http://localhost:8100` aux **Allowed Callback URLs** et aux **Allowed Logout URLs** de votre application Auth0 dans l’Auth0 Dashboard. N’oubliez pas de rétablir cette modification avant de générer la version native.
    </Warning>

    Pour l’exécuter sur un appareil ou dans un simulateur, ajoutez d’abord les plateformes natives :

    ```shellscript theme={null}
    npx cap add ios
    npx cap add android
    ```

    Ensuite, générez, synchronisez et exécutez :

    <CodeGroup>
      ```shellscript iOS theme={null}
      ionic build && npx cap sync && npx cap run ios
      ```

      ```shellscript Android theme={null}
      ionic build && npx cap sync && npx cap run android
      ```
    </CodeGroup>

    <Info>
      Vous devez ajouter les plateformes natives avec `npx cap add` avant de pouvoir les exécuter. Cette opération ne doit être effectuée qu’une seule fois par plateforme. Assurez-vous d’abord d’avoir enregistré le [schéma d’URL personnalisé](#custom-url-scheme-setup) pour votre plateforme.
    </Info>
  </Step>
</Steps>

<Check>
  **Point de contrôle**

  Vous devriez maintenant disposer d’une expérience de connexion Auth0 entièrement fonctionnelle dans votre application Ionic Vue, avec la connexion, la déconnexion et les informations du profil utilisateur.
</Check>

***

<div id="advanced-usage">
  ## Utilisation avancée
</div>

<Accordion title="Configuration d’un schéma d’URL personnalisé">
  Enregistrez le schéma d’URL personnalisé de votre application pour que le système d’exploitation puisse rediriger l’URL de rappel OAuth vers votre application après l’authentification.

  ### iOS

  Enregistrez votre schéma d’URL personnalisé dans `ios/App/App/Info.plist` :

  ```xml theme={null}
  <key>CFBundleURLTypes</key>
  <array>
    <dict>
      <key>CFBundleURLSchemes</key>
      <array>
        <string>YOUR_PACKAGE_ID</string>
      </array>
    </dict>
  </array>
  ```

  Remplacez `YOUR_PACKAGE_ID` par le `appId` de votre fichier `capacitor.config.ts`. Pour en savoir plus, consultez [Defining a Custom URL Scheme](https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app).

  ### Android

  Ajoutez un filtre d’intent à votre `android/app/src/main/AndroidManifest.xml`, à l’intérieur de la balise principale `<activity>` :

  ```xml theme={null}
  <intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="YOUR_PACKAGE_ID" />
  </intent-filter>
  ```

  Pour en savoir plus, consultez [Create Deep Links to App Content](https://developer.android.com/training/app-links/deep-linking).

  <Tip>
    Après avoir modifié les fichiers du projet natif, exécutez `npx cap sync` pour vous assurer que vos changements sont pris en compte.
  </Tip>
</Accordion>

<Accordion title="Protection des routes avec Vue Router">
  Utilisez le `authGuard` intégré du SDK Auth0 Vue pour protéger les routes qui nécessitent une authentification :

  ```typescript src/router/index.ts theme={null}
  import { createRouter, createWebHistory } from '@ionic/vue-router'
  import { authGuard } from '@auth0/auth0-vue'
  import HomePage from '../views/HomePage.vue'
  import ProfilePage from '../views/ProfilePage.vue'

  const routes = [
    {
      path: '/',
      name: 'Home',
      component: HomePage,
    },
    {
      path: '/profile',
      name: 'Profile',
      component: ProfilePage,
      beforeEnter: authGuard,
    },
  ]

  const router = createRouter({
    history: createWebHistory(import.meta.env.BASE_URL),
    routes,
  })

  export default router
  ```

  Le `authGuard` redirige automatiquement les utilisateurs non authentifiés vers la page Universal Login d’Auth0. Après la connexion, ils sont redirigés vers la route demandée au départ.
</Accordion>

<Accordion title="Appel d’API protégées">
  Configurez le paramètre `audience` dans votre configuration `createAuth0` pour demander des jetons d’accès pour votre API :

  ```typescript src/main.ts theme={null}
  app.use(
    createAuth0({
      domain: '{yourDomain}',
      clientId: '{yourClientId}',
      useRefreshTokens: true,
      useRefreshTokensFallback: false,
      authorizationParams: {
        redirect_uri,
        audience: 'YOUR_API_IDENTIFIER',
      },
    })
  )
  ```

  Utilisez ensuite `getAccessTokenSilently` dans vos composants pour récupérer des jetons et effectuer des appels d’API authentifiés :

  ```vue src/components/ApiCall.vue theme={null}
  <template>
    <ion-button @click="callApi" :disabled="loading">
      {{ loading ? 'Calling...' : 'Call Protected API' }}
    </ion-button>
    <pre v-if="response">{{ JSON.stringify(response, null, 2) }}</pre>
  </template>

  <script setup lang="ts">
  import { ref } from 'vue'
  import { useAuth0 } from '@auth0/auth0-vue'
  import { IonButton } from '@ionic/vue'

  const { getAccessTokenSilently } = useAuth0()
  const response = ref(null)
  const loading = ref(false)

  const callApi = async () => {
    try {
      loading.value = true
      const token = await getAccessTokenSilently()

      const res = await fetch('https://your-api.com/endpoint', {
        headers: {
          Authorization: `Bearer ${token}`,
        },
      })

      response.value = await res.json()
    } catch (error) {
      console.error('API call failed:', error)
    } finally {
      loading.value = false
    }
  }
  </script>
  ```

  <Tip>
    La méthode `getAccessTokenSilently` récupère le jeton depuis le cache ou l’actualise automatiquement au moyen du jeton d’actualisation, au besoin.
  </Tip>
</Accordion>

<Accordion title="Utilisation du modèle defineComponent">
  Si vous préférez le modèle explicite `defineComponent` à `<script setup>`, voici à quoi ressemble le composant LoginButton avec cette approche :

  ```vue src/components/LoginButton.vue theme={null}
  <template>
    <ion-button @click="login" expand="block">Log in</ion-button>
  </template>

  <script lang="ts">
  import { defineComponent } from 'vue'
  import { useAuth0 } from '@auth0/auth0-vue'
  import { Browser } from '@capacitor/browser'
  import { IonButton } from '@ionic/vue'

  export default defineComponent({
    components: { IonButton },
    setup() {
      const { loginWithRedirect } = useAuth0()

      const login = async () => {
        await loginWithRedirect({
          openUrl: (url: string) =>
            Browser.open({ url, windowName: '_self' }),
        })
      }

      return { login }
    },
  })
  </script>
  ```

  Le modèle `defineComponent` exige d’enregistrer explicitement les composants enfants et de retourner les valeurs à partir de la fonction `setup()`. Les deux modèles sont entièrement pris en charge par le SDK Auth0 Vue.
</Accordion>

<Accordion title="Problèmes courants et solutions">
  ### Erreur de non-correspondance de l’URL de rappel

  **Solution :** Vérifiez que l’URL de rappel dans votre Auth0 Dashboard correspond exactement à l’URL construite dans votre application. Assurez-vous que `YOUR_PACKAGE_ID` correspond au champ `appId` de votre `capacitor.config.ts`.

  ### Erreur « PKCE not allowed »

  **Correctif :**

  1. Accédez à Auth0 Dashboard > Applications > Your Application
  2. Remplacez le **type d’application** par **Native**
  3. Définissez **Token Endpoint Authentication Method** sur `None`
  4. Enregistrez les modifications et réessayez

  ### Le SSO ne fonctionne pas sur iOS

  Le plugin Browser de Capacitor utilise `SFSafariViewController`, qui ne partage pas les témoins avec Safari sur iOS 11+. Si vous avez besoin du SSO, utilisez un plugin compatible qui utilise [ASWebAuthenticationSession](https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession).

  ### La connexion fonctionne, mais l’utilisateur reste non authentifié après le redémarrage de l’application

  Activez `cacheLocation: 'localstorage'` dans la configuration `createAuth0` pour conserver les jetons d’une ouverture de l’application à l’autre. Tenez compte des [implications de sécurité](https://auth0.com/docs/libraries/auth0-single-page-app-sdk#change-storage-options). Le SDK prend aussi en charge des [implémentations de cache personnalisées](https://github.com/auth0/auth0-spa-js/blob/master/EXAMPLES.md#creating-a-custom-cache) pour un stockage plus sécurisé.

  ### Le navigateur ne se ferme pas après la connexion

  Assurez-vous d’appeler `Browser.close()` dans l’écouteur d’événement `appUrlOpen` de votre composant `App.vue`. Sur Android, `Browser.close()` n’a aucun effet; le navigateur se ferme donc automatiquement.

  ### La page de connexion s’ouvre dans l’application de navigateur par défaut de l’appareil

  Si la page de connexion s’ouvre dans Safari ou Chrome au lieu d’une fenêtre de navigateur intégrée à l’application, assurez-vous de transmettre le callback `openUrl` à `loginWithRedirect` et à `logout`. Sinon, le SDK utilise par défaut `window.location.href`, ce qui redirige l’ensemble de l’application.
</Accordion>
