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

> Ajoutez l’authentification Auth0 à une application Web Flask avec connexion, routes protégées et profils utilisateur

# Ajouter la connexion à votre application Flask

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

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 />

<Note>
  **Prérequis :** Avant de commencer, assurez-vous d’avoir installé les éléments suivants :

  * **[Python](https://www.python.org/downloads/)** 3.9 ou une version ultérieure
  * **[pip](https://pip.pypa.io/en/stable/installation/)** 20.0 ou une version ultérieure
  * **[jq](https://jqlang.org/)** - Nécessaire pour configurer l’Auth0 CLI

  **Compatibilité avec les versions de Flask :** Ce guide de démarrage rapide utilise **Flask 2.0+** avec l’extra `[async]` pour la prise en charge de l’asynchrone.
</Note>

<div id="get-started">
  ## Commencer
</div>

Ce guide de démarrage rapide montre comment ajouter l’authentification Auth0 à une application Flask. Vous créerez une application Web sécurisée avec une fonction de connexion, des routes protégées et l’accès au profil utilisateur à l’aide du [SDK Python Auth0 WebApp](https://github.com/auth0/auth0-server-python).

<Steps>
  <Step title="Configurez votre environnement" stepNumber={1}>
    Créez un nouveau répertoire pour votre projet Flask :

    ```bash theme={null}
    mkdir auth0-flask-app && cd auth0-flask-app
    ```

    Créez un environnement virtuel :

    ```bash theme={null}
    python -m venv venv
    source venv/bin/activate  # Sur Windows : venv\Scripts\activate
    ```
  </Step>

  <Step title="Installer les dépendances" stepNumber={2}>
    Créez `requirements.txt` pour suivre vos dépendances :

    ```txt requirements.txt theme={null}
    auth0-server-python>=1.0.0b7
    flask[async]>=2.0.0
    python-dotenv>=1.0.0
    ```

    Le fichier `requirements.txt` répertorie toutes les dépendances du projet. Pour les installer, exécutez :

    ```bash theme={null}
    pip install -r requirements.txt
    ```
  </Step>

  <Step title="Configurez votre Auth0 App" stepNumber={3}>
    Ensuite, vous devez créer une nouvelle application sur votre tenant Auth0 et ajouter les variables d'environnement à votre projet.

    Vous pouvez configurer automatiquement votre application Auth0 en exécutant une commande CLI ou le faire manuellement via le Dashboard :

    <Tabs>
      <Tab title="CLI">
        Exécutez la commande shell suivante dans le répertoire racine de votre projet pour créer une application Auth0 et générer un fichier `.env` :

        <CodeGroup>
          ```shellscript Mac theme={null}
          # Installez Auth0 CLI (s’il n’est pas déjà installé)
          brew tap auth0/auth0-cli && brew install auth0

          # Configurez l’application Auth0 et générez le fichier .env
          auth0 qs setup --app --type regular --framework vanilla-python --port 5000 --name "My Flask App"
          ```

          ```powershell Windows theme={null}
          # Installez Auth0 CLI (s’il n’est pas déjà installé)
          scoop bucket add auth0 https://github.com/auth0/scoop-auth0-cli.git
          scoop install auth0

          # Configurez l’application Auth0 et générez le fichier .env
          auth0 qs setup --app --type regular --framework vanilla-python --port 5000 --name "My Flask App"
          ```
        </CodeGroup>

        <Note>
          Cette commande va :

          1. Vérifier si vous êtes authentifié (et vous inviter à vous connecter au besoin)
          2. Créer une Auth0 Regular Web Application configurée pour `http://localhost:5000`
          3. Générer un fichier `.env` avec `AUTH0_DOMAIN`, `AUTH0_CLIENT_ID`, `AUTH0_CLIENT_SECRET`, `AUTH0_SECRET` et `AUTH0_REDIRECT_URI`
        </Note>
      </Tab>

      <Tab title="Dashboard">
        Avant de commencer, créez un fichier `.env` à la racine de votre projet :

        ```bash .env theme={null}
        # Configuration d’Auth0
        AUTH0_DOMAIN=YOUR_AUTH0_DOMAIN
        AUTH0_CLIENT_ID=YOUR_CLIENT_ID
        AUTH0_CLIENT_SECRET=YOUR_CLIENT_SECRET
        AUTH0_SECRET=YOUR_GENERATED_SECRET
        AUTH0_REDIRECT_URI=http://localhost:5000/callback
        ```

        1. Accédez à [Auth0 Dashboard](https://manage.auth0.com/dashboard/) → **Applications** → **Applications**
        2. Cliquez sur **Create Application**
        3. Donnez un nom à votre application (par ex., "My Flask App") et sélectionnez **Regular Web Application**
        4. Cliquez sur **Create**
        5. Dans l’onglet **Settings**, configurez les éléments suivants :
           * **Allowed Callback URLs** : `http://localhost:5000/callback`
           * **Allowed Logout URLs** : `http://localhost:5000`
           * **Allowed Web Origins** : `http://localhost:5000`
        6. Cliquez sur **Save Changes**
        7. Remplacez `YOUR_AUTH0_DOMAIN` dans `.env` par votre **Domain** de l’onglet **Settings** (par ex., `your-tenant.auth0.com`)
        8. Remplacez `YOUR_CLIENT_ID` dans `.env` par votre **Client ID**
        9. Remplacez `YOUR_CLIENT_SECRET` dans `.env` par votre **Client Secret**

        Générez un secret sécurisé pour `AUTH0_SECRET` :

        ```bash theme={null}
        openssl rand -hex 64
        ```

        <Info>
          **Important :** N’ajoutez jamais votre fichier `.env` au contrôle de version. Ajoutez-le à `.gitignore`.
        </Info>
      </Tab>
    </Tabs>
  </Step>

  <Step title="Créez la configuration d’authentification, les routes et les modèles" stepNumber={4}>
    Créer des fichiers

    ```bash theme={null}
    mkdir templates static && touch app.py auth.py templates/index.html templates/profile.html static/style.css
    ```

    Et ajoutez les extraits de code suivants :

    <AuthCodeGroup>
      ```python auth.py expandable lines theme={null}
      import os
      from auth0_server_python.auth_server.server_client import ServerClient
      from dotenv import load_dotenv

      load_dotenv()

      # Stockage en mémoire simple pour le développement
      # Pour la production, utilisez Redis, PostgreSQL ou un autre stockage persistant
      class MemoryStateStore:
          """In-memory state store for session data (development only)"""
          def __init__(self):
              self._data = {}
          
          async def get(self, key, options=None):
              return self._data.get(key)
          
          async def set(self, key, value, options=None):
              self._data[key] = value
          
          async def delete(self, key, options=None):
              self._data.pop(key, None)
          
          async def delete_by_logout_token(self, claims, options=None):
              # Pour la prise en charge du logout par canal arrière
              pass

      class MemoryTransactionStore:
          """In-memory transaction store for OAuth flows (development only)"""
          def __init__(self):
              self._data = {}
          
          async def get(self, key, options=None):
              return self._data.get(key)
          
          async def set(self, key, value, options=None):
              self._data[key] = value
          
          async def delete(self, key, options=None):
              self._data.pop(key, None)

      # Initialiser les magasins
      state_store = MemoryStateStore()
      transaction_store = MemoryTransactionStore()

      # Initialiser le Auth0 ServerClient
      auth0 = ServerClient(
          domain=os.getenv('AUTH0_DOMAIN'),
          client_id=os.getenv('AUTH0_CLIENT_ID'),
          client_secret=os.getenv('AUTH0_CLIENT_SECRET'),
          secret=os.getenv('AUTH0_SECRET'),
          redirect_uri=os.getenv('AUTH0_REDIRECT_URI'),
          state_store=state_store,
          transaction_store=transaction_store,
          authorization_params={
              'scope': 'openid profile email',
              'audience': os.getenv('AUTH0_AUDIENCE', '')  # Facultatif : pour l'accès à l'API
          }
      )
      ```

      ```python app.py expandable lines theme={null}
      import os
      from flask import Flask, redirect, render_template, request, url_for, g
      from auth0_server_python.auth_types import LogoutOptions
      from auth import auth0
      from dotenv import load_dotenv

      load_dotenv()

      app = Flask(__name__)
      app.secret_key = os.getenv('AUTH0_SECRET')

      # Configurer la session pour Auth0
      app.config.update(
          SESSION_COOKIE_SECURE=False,  # Mettre à True en production avec HTTPS
          SESSION_COOKIE_HTTPONLY=True,
          SESSION_COOKIE_SAMESITE='Lax',
      )

      @app.before_request
      def store_request_response():
          """Make request/response available for Auth0 SDK"""
          g.store_options = {"request": request}

      @app.route('/')
      async def index():
          """Home page - shows login button or user profile"""
          user = await auth0.get_user(g.store_options)
          return render_template('index.html', user=user)

      @app.route('/login')
      async def login():
          """Redirect to Auth0 login"""
          authorization_url = await auth0.start_interactive_login({}, g.store_options)
          return redirect(authorization_url)

      @app.route('/callback')
      async def callback():
          """Handle Auth0 callback after login"""
          try:
              result = await auth0.complete_interactive_login(str(request.url), g.store_options)
              return redirect(url_for('index'))
          except Exception as e:
              return f"Authentication error: {str(e)}", 400

      @app.route('/profile')
      async def profile():
          """Protected route - shows user profile"""
          user = await auth0.get_user(g.store_options)
          
          if not user:
              return redirect(url_for('login'))
          
          return render_template('profile.html', user=user)

      @app.route('/logout')
      async def logout():
          """Logout and redirect to Auth0 logout"""
          options = LogoutOptions(return_to=url_for("index", _external=True))
          logout_url = await auth0.logout(options, g.store_options)
          return redirect(logout_url)

      if __name__ == '__main__':
          app.run(debug=True, port=5000)
      ```

      ```html templates/index.html expandable lines theme={null}
      <!DOCTYPE html>
      <html lang="en">
      <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Flask + Auth0</title>
      <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
      </head>
      <body>
      <div class="container">
          <div class="card">
              <img src="https://cdn.auth0.com/quantum-assets/dist/latest/logos/auth0/auth0-lockup-en-ondark.png"
                   alt="Auth0 Logo" class="logo">
              <h1>Flask + Auth0</h1>
              
              {% if user %}
                  <div class="logged-in">
                      <p class="success">✅ Successfully logged in!</p>
                      <div class="user-info">
                          {% if user.picture %}
                          <img src="{{ user.picture }}" alt="Profile" class="profile-pic">
                          {% endif %}
                          <h2>{{ user.name }}</h2>
                          <p>{{ user.email }}</p>
                      </div>
                      <a href="/profile" class="button">View Full Profile</a>
                      <a href="/logout" class="button logout">Log Out</a>
                  </div>
              {% else %}
                  <div class="logged-out">
                      <p>Welcome! Please log in to access your protected content.</p>
                      <a href="/login" class="button">Log In</a>
                  </div>
              {% endif %}
          </div>
      </div>
      </body>
      </html>
      ```

      ```html templates/profile.html expandable lines theme={null}
      <!DOCTYPE html>
      <html lang="en">
      <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>User Profile - Flask + Auth0</title>
      <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
      </head>
      <body>
      <div class="container">
          <div class="card">
              <img src="https://cdn.auth0.com/quantum-assets/dist/latest/logos/auth0/auth0-lockup-en-ondark.png"
                   alt="Auth0 Logo" class="logo">
              <h1>User Profile</h1>
              
              <div class="profile-details">
                  {% if user.picture %}
                  <img src="{{ user.picture }}" alt="Profile" class="profile-pic-large">
                  {% endif %}
                  
                  <div class="profile-info">
                      <h2>{{ user.name }}</h2>
                      <p class="email">{{ user.email }}</p>
                      
                      <div class="profile-data">
                          <h3>Profile Information</h3>
                          <dl>
                              <dt>User ID:</dt>
                              <dd>{{ user.sub }}</dd>
                              
                              {% if user.nickname %}
                              <dt>Nickname:</dt>
                              <dd>{{ user.nickname }}</dd>
                              {% endif %}
                              
                              {% if user.updated_at %}
                              <dt>Last Updated:</dt>
                              <dd>{{ user.updated_at }}</dd>
                              {% endif %}
                          </dl>
                      </div>
                  </div>
              </div>
              
              <div class="actions">
                  <a href="/" class="button">Back to Home</a>
                  <a href="/logout" class="button logout">Log Out</a>
              </div>
          </div>
      </div>
      </body>
      </html>
      ```

      ```css static/style.css expandable lines theme={null}
      @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');

      * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
      }

      body {
      font-family: 'Inter', sans-serif;
      background: linear-gradient(135deg, #1a1e27 0%, #2d313c 100%);
      min-height: 100vh;
      display: flex;
      justify-content: center;
      align-items: center;
      color: #e2e8f0;
      padding: 20px;
      }

      .container {
      width: 100%;
      max-width: 600px;
      }

      .card {
      background-color: #262a33;
      border-radius: 20px;
      box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.05);
      padding: 3rem;
      animation: fadeInScale 0.6s ease-out;
      }

      @keyframes fadeInScale {
      from {
          opacity: 0;
          transform: scale(0.95);
      }
      to {
          opacity: 1;
          transform: scale(1);
      }
      }

      .logo {
      width: 160px;
      margin: 0 auto 2rem;
      display: block;
      animation: slideDown 0.8s ease-out;
      }

      @keyframes slideDown {
      from {
          opacity: 0;
          transform: translateY(-30px);
      }
      to {
          opacity: 1;
          transform: translateY(0);
      }
      }

      h1 {
      font-size: 2.5rem;
      font-weight: 700;
      text-align: center;
      margin-bottom: 2rem;
      color: #f7fafc;
      text-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
      }

      h2 {
      font-size: 1.8rem;
      font-weight: 600;
      margin: 0.5rem 0;
      color: #f7fafc;
      }

      h3 {
      font-size: 1.3rem;
      font-weight: 600;
      margin-top: 1.5rem;
      margin-bottom: 1rem;
      color: #cbd5e0;
      }

      .logged-in, .logged-out {
      text-align: center;
      }

      .logged-out p {
      font-size: 1.2rem;
      color: #cbd5e0;
      margin-bottom: 2rem;
      line-height: 1.6;
      }

      .success {
      font-size: 1.5rem;
      color: #68d391;
      font-weight: 600;
      margin-bottom: 1.5rem;
      }

      .user-info {
      background-color: #2d313c;
      border-radius: 15px;
      padding: 2rem;
      margin: 2rem 0;
      }

      .profile-pic {
      width: 80px;
      height: 80px;
      border-radius: 50%;
      margin-bottom: 1rem;
      border: 3px solid #63b3ed;
      object-fit: cover;
      }

      .profile-pic-large {
      width: 120px;
      height: 120px;
      border-radius: 50%;
      margin-bottom: 1rem;
      border: 4px solid #63b3ed;
      object-fit: cover;
      }

      .user-info p, .email {
      color: #a0aec0;
      font-size: 1.1rem;
      }

      .button {
      display: inline-block;
      padding: 1rem 2.5rem;
      font-size: 1.1rem;
      font-weight: 600;
      border-radius: 10px;
      border: none;
      cursor: pointer;
      transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
      text-decoration: none;
      text-transform: uppercase;
      letter-spacing: 0.08em;
      margin: 0.5rem;
      background-color: #63b3ed;
      color: #1a1e27;
      box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
      }

      .button:hover {
      background-color: #4299e1;
      transform: translateY(-3px);
      box-shadow: 0 12px 25px rgba(0, 0, 0, 0.5);
      }

      .button.logout {
      background-color: #fc8181;
      }

      .button.logout:hover {
      background-color: #e53e3e;
      }

      .profile-details {
      text-align: center;
      }

      .profile-info {
      background-color: #2d313c;
      border-radius: 15px;
      padding: 2rem;
      margin-top: 1.5rem;
      }

      .profile-data {
      margin-top: 2rem;
      text-align: left;
      }

      .profile-data dl {
      display: grid;
      grid-template-columns: 150px 1fr;
      gap: 1rem;
      margin-top: 1rem;
      }

      .profile-data dt {
      font-weight: 600;
      color: #cbd5e0;
      }

      .profile-data dd {
      color: #a0aec0;
      word-break: break-all;
      }

      .actions {
      margin-top: 2rem;
      display: flex;
      justify-content: center;
      flex-wrap: wrap;
      }

      @media (max-width: 600px) {
      .card {
          padding: 2rem;
      }

      h1 {
          font-size: 2rem;
      }

      .button {
          padding: 0.8rem 2rem;
          font-size: 1rem;
      }

      .logo {
          width: 120px;
      }

      .profile-data dl {
          grid-template-columns: 1fr;
          gap: 0.5rem;
      }

      .profile-data dt {
          margin-top: 1rem;
      }
      }
      ```
    </AuthCodeGroup>

    <Info>
      **Développement seulement :** Cet exemple utilise de simples classes de stockage en mémoire (`MemoryStateStore` et `MemoryTransactionStore`) à des fins de démonstration. Ces mécanismes de stockage perdront toutes les données de session au redémarrage de votre application et ne fonctionneront pas dans des déploiements à plusieurs instances.

      **Pour les applications de production**, vous devez mettre en place un stockage persistant. Le SDK est indépendant du framework et exige que vous fournissiez des implémentations personnalisées de `StateStore` et de `TransactionStore`. Consultez les [exemples officiels de stockage du SDK](https://github.com/auth0/auth0-server-python/blob/main/examples/ConfigureStore.md) pour des conseils détaillés sur la mise en œuvre de Redis, PostgreSQL ou d’autres systèmes de stockage persistants.
    </Info>
  </Step>

  <Step title="Lancez votre application" stepNumber={5}>
    Démarrez le serveur de développement Flask :

    ```bash theme={null}
    python app.py
    ```

    Votre application sera accessible à l’adresse [http://localhost:5000](http://localhost:5000). Le SDK Auth0 gère automatiquement les routes d’authentification.
  </Step>
</Steps>

<Check>
  **Vérification**

  Vous devriez maintenant disposer d’une page de connexion Auth0 entièrement fonctionnelle accessible sur votre [localhost](http://localhost:5000/)
</Check>

***

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

<Accordion title="Accéder aux jetons d’API">
  Si vous devez envoyer une requête à une API protégée, récupérez un jeton d’accès :

  ```python theme={null}
  @app.route('/api-call')
  @require_auth
  async def api_call():
      try:
          # Obtenir un jeton d’accès pour votre API
          access_token = await auth0.get_access_token(
              audience='https://your-api.example.com',
              store_options=g.store_options
          )
          
          # Utiliser le jeton pour appeler votre API
          # headers = {'Authorization': f'Bearer {access_token}'}
          # response = requests.get('https://your-api.example.com/data', headers=headers)
          
          return f"Access token retrieved: {access_token[:20]}..."
      except Exception as e:
          return f"Error getting access token: {str(e)}", 500
  ```

  <Info>
    Pour utiliser cette fonctionnalité, vous devez :

    1. Définir `AUTH0_AUDIENCE` dans votre fichier `.env`
    2. Inclure `offline_access` dans vos scopes (pour les refresh tokens)
    3. Mettre à jour `authorization_params` dans `auth.py` :
       ```python theme={null}
       authorization_params={
           'scope': 'openid profile email offline_access',
           'audience': os.getenv('AUTH0_AUDIENCE')
       }
       ```
  </Info>
</Accordion>

<Accordion title="Configuration du stockage personnalisé">
  Par défaut, le SDK utilise un stockage basé sur les cookies. Pour les environnements de production ayant des besoins particuliers (mise à l’échelle horizontale, partage de sessions entre services), vous pouvez configurer des backends de stockage personnalisés comme Redis ou PostgreSQL.

  **Quand utiliser un stockage personnalisé :**

  * Vous devez partager des sessions entre plusieurs serveurs
  * Vos données de session dépassent les limites de taille des cookies
  * Vous avez besoin d’une gestion centralisée des sessions pour le backchannel logout

  **Exemple avec Redis :**

  ```python auth.py theme={null}
  from auth0_server_python.stores.redis_state_store import RedisStateStore
  import redis.asyncio as redis

  # Initialiser un magasin d’état personnalisé
  redis_client = redis.from_url(os.getenv('REDIS_URL', 'redis://localhost:6379'))
  state_store = RedisStateStore(
      secret=os.getenv('AUTH0_SECRET'),
      redis_client=redis_client
  )

  # Passer à ServerClient
  auth0 = ServerClient(
      domain=os.getenv('AUTH0_DOMAIN'),
      client_id=os.getenv('AUTH0_CLIENT_ID'),
      client_secret=os.getenv('AUTH0_CLIENT_SECRET'),
      secret=os.getenv('AUTH0_SECRET'),
      redirect_uri=os.getenv('AUTH0_REDIRECT_URI'),
      state_store=state_store,  # Stockage personnalisé
      authorization_params={'scope': 'openid profile email'}
  )
  ```

  <Info>
    Pour la plupart des applications, le stockage par défaut basé sur les cookies suffit. Le stockage personnalisé exige l’implémentation de l’interface `StateStore`. Consultez les [exemples du SDK](https://github.com/auth0/auth0-server-python/blob/main/examples/ConfigureStore.md) pour voir des mises en œuvre détaillées.
  </Info>
</Accordion>

***

<div id="common-issues">
  ## Problèmes courants
</div>

<AccordionGroup>
  <Accordion title="MissingRequiredArgumentError">
    **Problème :** Vous voyez "MissingRequiredArgumentError: secret" au démarrage de l’application

    **Cause :** La variable d’environnement `AUTH0_SECRET` est absente ou n’est pas chargée correctement.

    **Solution :**

    1. Vérifiez que votre fichier `.env` se trouve à la racine du projet
    2. Assurez-vous que `python-dotenv` est installé : `pip install python-dotenv`
    3. Générez un nouveau secret au besoin : `openssl rand -hex 64`
    4. Ajoutez-le au fichier `.env` : `AUTH0_SECRET=your_generated_secret`
    5. Redémarrez votre application Flask
  </Accordion>

  <Accordion title="Erreur : URL de rappel invalide">
    **Problème :** Vous voyez l’erreur "Callback URL mismatch" ou "invalid\_request" lors de la connexion

    **Cause :** Le Redirect URI dans votre code ne correspond pas à ce qui est enregistré dans Auth0 Dashboard.

    **Solution :**

    1. Vérifiez votre fichier `.env` : `AUTH0_REDIRECT_URI=http://localhost:5000/callback`
    2. Accédez à [Auth0 Dashboard](https://manage.auth0.com/dashboard/) → Applications → Votre application → Settings
    3. Ajoutez `http://localhost:5000/callback` à **Allowed Callback URLs**
    4. Cliquez sur **Save Changes**
    5. Redémarrez votre application Flask
  </Accordion>

  <Accordion title="Erreurs de la boucle d’événements AsyncIO">
    **Problème :** Vous voyez "RuntimeError: This event loop is already running" ou une erreur asynchrone similaire

    **Cause :** La prise en charge asynchrone de Flask 2.0+ peut poser problème avec certaines configurations.

    **Solution :**

    Installez Flask avec la prise en charge asynchrone :

    ```bash theme={null}
    pip install "flask[async]"
    ```

    Redémarrez ensuite votre application Flask.
  </Accordion>

  <Accordion title="Erreurs « module introuvable »">
    **Problème :** Vous voyez "ModuleNotFoundError: No module named 'auth0\_server\_python'" ou un message similaire

    **Cause :** Le SDK n’est pas installé ou l’environnement virtuel n’est pas activé.

    **Solution :**

    1. Assurez-vous que votre environnement virtuel est activé :
       ```bash theme={null}
       source venv/bin/activate  # macOS/Linux
       # ou
       venv\Scripts\activate  # Windows
       ```
    2. Installez le SDK :
       ```bash theme={null}
       pip install auth0-server-python "flask[async]" python-dotenv
       ```
    3. Vérifiez l’installation :

    ```bash theme={null}
    pip list | grep auth0
    ```
  </Accordion>

  <Accordion title="ClaimDecodingFailed Error">
    **Problème :** Vous voyez l’erreur "ClaimDecodingFailed" ou "Failed to decode claims" pendant l’authentification

    **Cause :** Le ID token ou le jeton d’accès reçu d’Auth0 n’a pas pu être décodé correctement, souvent pour l’une des raisons suivantes :

    * Format JWT invalide
    * Données de session corrompues
    * Algorithmes de signature incompatibles
    * Décalage horaire entre votre serveur et Auth0

    **Solution :**

    1. Assurez-vous que votre `AUTH0_CLIENT_SECRET` est correct dans le fichier `.env`
    2. Vérifiez que l’heure de votre système est synchronisée (NTP) :
       ```bash theme={null}
       # macOS
       sudo sntp -sS time.apple.com

       # Linux
       sudo ntpdate -s time.nist.gov
       ```
    3. Effacez les cookies du navigateur et relancez l’authentification
    4. Vérifiez que `AUTH0_DOMAIN` n’inclut pas le préfixe `https://`
    5. Vérifiez que Auth0 Dashboard → Applications → Your App → Settings → Advanced → OAuth → JsonWebToken Signature Algorithm correspond à la configuration de votre SDK
  </Accordion>

  <Accordion title="Token expiré ou invalide">
    **Problème :** Vous voyez les erreurs "Token has expired" ou "invalid\_token"

    **Cause :** Le jeton d’accès ou l’ID token a dépassé sa durée de validité, ou la session a expiré.

    **Solution :**

    1. Le SDK gère automatiquement l’actualisation du jeton si vous incluez la portée `offline_access` :
       ```python theme={null}
       authorization_params={
           'scope': 'openid profile email offline_access',
       }
       ```
    2. Pour les API, assurez-vous de demander de nouveaux jetons :
       ```python theme={null}
       access_token = await auth0.get_access_token(
           audience='https://your-api.example.com',
           force_refresh=True  # Forcer l’actualisation au besoin
       )
       ```
    3. Ajustez la durée de validité des jetons dans Auth0 Dashboard → Applications → Your App → Settings → Advanced → OAuth
    4. Prévoyez une gestion appropriée des erreurs afin de rediriger les utilisateurs vers la page de connexion lorsque les jetons expirent
  </Accordion>

  <Accordion title="CORS et erreurs d’origine croisée">
    **Problème :** Vous voyez des erreurs CORS ou "Blocked by CORS policy" dans la console du navigateur

    **Cause :** L’origine de votre application n’est pas configurée correctement dans Auth0.

    **Solution :**

    1. Ajoutez l’origine de votre application dans Auth0 Dashboard → Applications → Your App → Settings:
       * **Allowed Web Origins**: `http://localhost:5000`
       * **Allowed Callback URLs**: `http://localhost:5000/callback`
       * **Allowed Logout URLs**: `http://localhost:5000`
    2. En Production, ajoutez vos URL de production :
       ```
       https://yourdomain.com
       https://yourdomain.com/callback
       ```
    3. Assurez-vous que votre application Flask a une configuration CORS appropriée si elle envoie des requêtes aux API Auth0 depuis le code Javascript côté client :
       ```python theme={null}
       from flask_cors import CORS
       CORS(app, origins=['http://localhost:5000'])
       ```
  </Accordion>

  <Accordion title="Limite de requêtes dépassée">
    **Problème :** Vous voyez les erreurs "Too many requests" ou "Rate limit exceeded"

    **Cause :** Votre application a dépassé les limites de débit d’Auth0 pour les requêtes d’authentification.

    **Solution :**

    1. Consultez Auth0 Dashboard → Monitoring → Logs pour obtenir des détails sur les limites de débit
    2. Mettez en place une temporisation exponentielle pour les nouvelles tentatives :
       ```python theme={null}
       import time
       from auth0_server_python.error import ApiError

       async def login_with_retry():
           max_retries = 3
           for attempt in range(max_retries):
               try:
                   return await auth0.start_interactive_login({}, g.store_options)
               except ApiError as e:
                   if e.status_code == 429 and attempt < max_retries - 1:
                       wait_time = 2 ** attempt
                       time.sleep(wait_time)
                   else:
                       raise
       ```
    3. Vérifiez les limites de votre forfait d’abonnement Auth0
    4. Optimisez le flux d’authentification pour réduire les requêtes de jeton inutiles
    5. Mettez les jetons en cache de façon appropriée au lieu d’en demander souvent de nouveaux
  </Accordion>
</AccordionGroup>
