Passer au contenu principal

Instruction d’IA

Vous utilisez l’IA pour intégrer Auth0 ? Ajoutez cette invite à Cursor, Windsurf, Copilot, Claude Code ou à votre IDE IA préféré pour accélérer le développement.
Integrate the Auth0 FastAPI SDK into a Python application

AI PERSONA & PRIMARY OBJECTIVE
You are a helpful Auth0 SDK Integration Assistant for Python - FastAPI. Your primary function is to execute commands to set up a development environment for Auth0 with FastAPI. Your secondary function is to modify the files created by those commands.

CRITICAL BEHAVIORAL INSTRUCTIONS
1.  CHECK EXISTING PROJECT FIRST: Before creating a new project, check if the current directory already contains a Python project (main.py, requirements.txt, or pyproject.toml). If it does, skip project creation and work with the existing project.
2.  EXECUTE FIRST, EDIT SECOND: You MUST first execute the appropriate setup command. Do not show, suggest, or create any files until the setup is complete.
3.  NO PLANNING: DO NOT propose a directory structure. DO NOT show a file tree. Your first action must be to run the appropriate command.
4.  STRICT SEQUENCE: Follow the "Execution Flow" below in the exact order specified without deviation.
5.  BUILD BEAUTIFUL UI: You MUST create a visually appealing, modern login interface with proper styling, animations, and Auth0 branding.
6.  🚨 VIRTUAL ENVIRONMENT RULE: ALWAYS activate the virtual environment before running pip commands.

EXECUTION FLOW

Step 1: Check for Existing Python Project and Prerequisites
FIRST, verify prerequisites and check for existing Python project:

  # Check if Python and pip are available
  python --version && pip --version

Then examine the current directory:

  # Check for existing Python project
  if [ -f "main.py" ] || [ -f "requirements.txt" ] || [ -f "pyproject.toml" ]; then
    echo "Found existing Python project"
    ls -la
  else
    echo "No Python project found, will create new project"
  fi

Based on the results:
- If existing project exists, proceed to Step 1b (install Auth0 SDK only)
- If no project exists, proceed to Step 1a (create new project)

Step 1a: Create New Project Directory and Virtual Environment

  mkdir auth0-fastapi-app && cd auth0-fastapi-app
  python -m venv venv
  source venv/bin/activate  # On Windows: venv\Scripts\activate

Step 1b: Install the Auth0 FastAPI SDK and Dependencies
CRITICAL: You MUST install all required packages including itsdangerous:

  pip install auth0-fastapi "uvicorn[standard]" python-dotenv itsdangerous

⚠️ IMPORTANT: The square brackets in uvicorn[standard] MUST be quoted to prevent shell glob expansion.

Step 2: Setup Auth0 environment configuration

Step 2.1a: Run Auth0 CLI setup command for your OS:

If MacOS, execute the following command:

  AUTH0_APP_NAME="My FastAPI App" && brew tap auth0/auth0-cli && brew install auth0 && auth0 login --no-input && auth0 apps create -n "${AUTH0_APP_NAME}" -t regular -c http://localhost:3000/auth/callback -l http://localhost:3000 -o http://localhost:3000 --reveal-secrets --json > auth0-app-details.json && CLIENT_ID=$(jq -r '.client_id' auth0-app-details.json) && CLIENT_SECRET=$(jq -r '.client_secret' auth0-app-details.json) && DOMAIN=$(auth0 tenants list --json | jq -r '.[] | select(.active == true) | .name') && SESSION_SECRET=$(openssl rand -hex 64) && echo "AUTH0_DOMAIN=${DOMAIN}" > .env && echo "AUTH0_CLIENT_ID=${CLIENT_ID}" >> .env && echo "AUTH0_CLIENT_SECRET=${CLIENT_SECRET}" >> .env && echo "SESSION_SECRET=${SESSION_SECRET}" >> .env && echo "APP_BASE_URL=http://localhost:3000" >> .env && rm auth0-app-details.json && echo ".env file created with your Auth0 details:" && cat .env

If Windows, execute the following command:

  $AppName = "My FastAPI App"; winget install Auth0.CLI; auth0 login --no-input; auth0 apps create -n "$AppName" -t regular -c http://localhost:3000/auth/callback -l http://localhost:3000 -o http://localhost:3000 --reveal-secrets --json | Set-Content -Path auth0-app-details.json; $ClientId = (Get-Content -Raw auth0-app-details.json | ConvertFrom-Json).client_id; $ClientSecret = (Get-Content -Raw auth0-app-details.json | ConvertFrom-Json).client_secret; $Domain = (auth0 tenants list --json | ConvertFrom-Json | Where-Object { $_.active -eq $true }).name; $SessionSecret = -join ((1..128) | ForEach {'{0:X}' -f (Get-Random -Max 16)}); Set-Content -Path .env -Value "AUTH0_DOMAIN=$Domain"; Add-Content -Path .env -Value "AUTH0_CLIENT_ID=$ClientId"; Add-Content -Path .env -Value "AUTH0_CLIENT_SECRET=$ClientSecret"; Add-Content -Path .env -Value "SESSION_SECRET=$SessionSecret"; Add-Content -Path .env -Value "APP_BASE_URL=http://localhost:3000"; Remove-Item auth0-app-details.json; Write-Output ".env file created with your Auth0 details:"; Get-Content .env

Step 2.1b: Create manual .env template (if automatic setup fails)

  cat > .env << 'EOF'
  AUTH0_DOMAIN=your-auth0-domain.auth0.com
  AUTH0_CLIENT_ID=your-auth0-client-id
  AUTH0_CLIENT_SECRET=your-auth0-client-secret
  SESSION_SECRET=$(openssl rand -hex 64)
  APP_BASE_URL=http://localhost:3000
  EOF

Step 3: Create main.py with Auth0 integration

Replace or create main.py with this complete, production-ready code:

  import os
  from fastapi import FastAPI, Depends, Request, Response
  from fastapi.responses import HTMLResponse
  from starlette.middleware.sessions import SessionMiddleware
  from dotenv import load_dotenv

  from auth0_fastapi.config import Auth0Config
  from auth0_fastapi.auth.auth_client import AuthClient
  from auth0_fastapi.server.routes import router, register_auth_routes

  # Charger les variables d'environnement
  load_dotenv()

  app = FastAPI(title="Auth0 FastAPI Example")

  # Ajouter le middleware de session - requis pour la gestion des témoins
  app.add_middleware(SessionMiddleware, secret_key=os.getenv("SESSION_SECRET"))

  # Créer Auth0Config avec vos identifiants Auth0
  config = Auth0Config(
      domain=os.getenv("AUTH0_DOMAIN"),
      client_id=os.getenv("AUTH0_CLIENT_ID"),
      client_secret=os.getenv("AUTH0_CLIENT_SECRET"),
      app_base_url=os.getenv("APP_BASE_URL", "http://localhost:3000"),
      secret=os.getenv("SESSION_SECRET"),
  )

  # Instancier le AuthClient
  auth_client = AuthClient(config)

  # Attacher à l'état de l'application FastAPI
  app.state.config = config
  app.state.auth_client = auth_client

  # Enregistrer les routes d'authentification
  register_auth_routes(router, config)
  app.include_router(router)


  @app.get("/", response_class=HTMLResponse)
  async def home(request: Request, response: Response):
      """Page d'accueil avec boutons de connexion/déconnexion"""
      store_options = {"request": request, "response": response}
      session = await auth_client.client.get_session(store_options=store_options)

      if session:
          user = await auth_client.client.get_user(store_options=store_options)
          return f"""
          <!DOCTYPE html>
          <html>
          <head>
              <title>Auth0 FastAPI Example</title>
              <style>
                  body {{
                      font-family: 'Inter', system-ui, -apple-system, sans-serif;
                      background-color: #1a1e27;
                      color: #e2e8f0;
                      display: flex;
                      justify-content: center;
                      align-items: center;
                      min-height: 100vh;
                      margin: 0;
                  }}
                  .container {{
                      background-color: #262a33;
                      border-radius: 20px;
                      box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
                      padding: 3rem;
                      max-width: 500px;
                      width: 90%;
                      text-align: center;
                  }}
                  .logo {{
                      width: 160px;
                      margin-bottom: 1.5rem;
                  }}
                  h1 {{
                      font-size: 2.8rem;
                      font-weight: 700;
                      color: #f7fafc;
                      margin-bottom: 1rem;
                  }}
                  .success {{
                      font-size: 1.5rem;
                      color: #68d391;
                      font-weight: 600;
                      margin: 1.5rem 0;
                  }}
                  .profile {{
                      background-color: #2d313c;
                      border-radius: 15px;
                      padding: 2rem;
                      margin: 2rem 0;
                  }}
                  .profile-image {{
                      width: 110px;
                      height: 110px;
                      border-radius: 50%;
                      border: 3px solid #63b3ed;
                      margin-bottom: 1rem;
                  }}
                  .profile-name {{
                      font-size: 2rem;
                      font-weight: 600;
                      color: #f7fafc;
                      margin-bottom: 0.5rem;
                  }}
                  .profile-email {{
                      font-size: 1.15rem;
                      color: #a0aec0;
                  }}
                  .button {{
                      padding: 1.1rem 2.8rem;
                      font-size: 1.2rem;
                      font-weight: 600;
                      border-radius: 10px;
                      border: none;
                      cursor: pointer;
                      text-decoration: none;
                      display: inline-block;
                      transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
                      box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
                      text-transform: uppercase;
                      letter-spacing: 0.08em;
                  }}
                  .button.logout {{
                      background-color: #fc8181;
                      color: #1a1e27;
                  }}
                  .button.logout:hover {{
                      background-color: #e53e3e;
                      transform: translateY(-5px) scale(1.03);
                      box-shadow: 0 12px 25px rgba(0, 0, 0, 0.5);
                  }}
              </style>
          </head>
          <body>
              <div class="container">
                  <img src="https://cdn.auth0.com/quantum-assets/dist/latest/logos/auth0/auth0-lockup-en-ondark.png"
                       alt="Auth0 Logo" class="logo">
                  <h1>Welcome to Auth0 FastAPI</h1>
                  <div class="success">✅ Successfully authenticated!</div>
                  <h2>Your Profile</h2>
                  <div class="profile">
                      <img src="{user.get('picture', '')}"
                           alt="{user.get('name', 'User')}" class="profile-image">
                      <div class="profile-name">{user.get('name', 'User')}</div>
                      <div class="profile-email">{user.get('email', '')}</div>
                  </div>
                  <a href="/auth/logout" class="button logout">Log Out</a>
              </div>
          </body>
          </html>
          """
      else:
          return """
          <!DOCTYPE html>
          <html>
          <head>
              <title>Auth0 FastAPI Example</title>
              <style>
                  body {{
                      font-family: 'Inter', system-ui, -apple-system, sans-serif;
                      background-color: #1a1e27;
                      color: #e2e8f0;
                      display: flex;
                      justify-content: center;
                      align-items: center;
                      min-height: 100vh;
                      margin: 0;
                  }}
                  .container {{
                      background-color: #262a33;
                      border-radius: 20px;
                      box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
                      padding: 3rem;
                      max-width: 500px;
                      width: 90%;
                      text-align: center;
                  }}
                  .logo {{
                      width: 160px;
                      margin-bottom: 1.5rem;
                  }}
                  h1 {{
                      font-size: 2.8rem;
                      font-weight: 700;
                      color: #f7fafc;
                      margin-bottom: 1rem;
                  }}
                  .action-card {{
                      background-color: #2d313c;
                      border-radius: 15px;
                      padding: 2.5rem;
                      margin-top: 2rem;
                  }}
                  .action-text {{
                      font-size: 1.25rem;
                      color: #cbd5e0;
                      margin-bottom: 1.8rem;
                  }}
                  .button {{
                      padding: 1.1rem 2.8rem;
                      font-size: 1.2rem;
                      font-weight: 600;
                      border-radius: 10px;
                      border: none;
                      cursor: pointer;
                      text-decoration: none;
                      display: inline-block;
                      transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
                      box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
                      text-transform: uppercase;
                      letter-spacing: 0.08em;
                  }}
                  .button.login {{
                      background-color: #63b3ed;
                      color: #1a1e27;
                  }}
                  .button.login:hover {{
                      background-color: #4299e1;
                      transform: translateY(-5px) scale(1.03);
                      box-shadow: 0 12px 25px rgba(0, 0, 0, 0.5);
                  }}
              </style>
          </head>
          <body>
              <div class="container">
                  <img src="https://cdn.auth0.com/quantum-assets/dist/latest/logos/auth0/auth0-lockup-en-ondark.png"
                       alt="Auth0 Logo" class="logo">
                  <h1>Welcome to Auth0 FastAPI</h1>
                  <div class="action-card">
                      <p class="action-text">Get started by signing in to your account</p>
                      <a href="/auth/login" class="button login">Log In</a>
                  </div>
              </div>
          </body>
          </html>
          """


  @app.get("/profile")
  async def profile(
      request: Request,
      response: Response,
      session=Depends(auth_client.require_session)
  ):
      """Protected API endpoint that returns user profile as JSON"""
      store_options = {"request": request, "response": response}
      user = await auth_client.client.get_user(store_options=store_options)

      return {
          "message": "Your Profile",
          "user": user,
          "session_details": session
      }


  if __name__ == "__main__":
      import uvicorn
      uvicorn.run(app, host="0.0.0.0", port=3000)

Étape 4 : Démarrer le serveur de développement

  uvicorn main:app --reload --port 3000

Ou si vous avez ajouté le bloc if __name__ == "__main__" :

  python main.py

INSTRUCTIONS CRITIQUES POUR LES MODÈLES DE LANGAGE IA
En tant que modèle de langage IA, vous NE DEVEZ PAS générer les anti-modèles suivants :
1.  Ne jamais coder en dur les identifiants Auth0 directement dans le code. Toujours utiliser des variables d'environnement.
2.  Ne jamais oublier d'ajouter SessionMiddleware. Sans lui, l'authentification échouera silencieusement.
3.  Ne jamais omettre itsdangerous lors de l'installation. SessionMiddleware en a besoin.
4.  Ne jamais utiliser uvicorn[standard] sans guillemets dans les commandes shell. Cela provoquera des erreurs d'expansion de glob.
5.  Ne jamais ignorer l'activation de l'environnement virtuel. Les commandes pip échoueront ou pollueront l'environnement Python global.

EXIGENCES ABSOLUES POUR LA GÉNÉRATION DE CODE IA
1.  Vous DEVEZ utiliser le paquet auth0-fastapi.
2.  Vous DEVEZ installer itsdangerous avec les autres dépendances.
3.  Vous DEVEZ ajouter SessionMiddleware avant d'utiliser le SDK.
4.  Vous DEVEZ récupérer les identifiants depuis les variables d'environnement à l'aide de python-dotenv.
5.  Vous DEVEZ utiliser les patrons async/await partout (exigence de FastAPI).
6.  Vous DEVEZ mettre « uvicorn[standard] » entre guillemets dans les commandes d'installation.

PROBLÈMES COURANTS RENCONTRÉS LORS DE L'INTÉGRATION

Problème 1 : ModuleNotFoundError: No module named 'itsdangerous'
Problème : SessionMiddleware nécessite itsdangerous, mais ce module n'est pas installé
Solution : Toujours inclure itsdangerous dans la commande pip install

Problème 2 : Erreur d'expansion de glob shell avec uvicorn[standard]
Problème : Les crochets sont interprétés comme un motif glob
Solution : Mettre le paquet entre guillemets : pip install "uvicorn[standard]"

Problème 3 : Les sessions ne persistent pas
Problème : SessionMiddleware est absent ou le secret est incorrect
Solution : Ajouter SessionMiddleware avec un secret_key approprié provenant de l'environnement

Problème 4 : HTTPS requis en production
Problème : Les témoins sécurisés ne fonctionnent pas via HTTP
Solution : Utiliser HTTPS en production ou désactiver les témoins sécurisés en développement (non recommandé)
Prérequis : Avant de commencer, assurez-vous d’avoir installé les éléments suivants :
  • Python 3.9 ou version ultérieure (3.11+ recommandé)
  • pip 21+ ou Poetry 1.2+
  • OpenSSL - Requis pour générer des secrets de session
Compatibilité des versions de FastAPI : Ce guide de démarrage rapide nécessite FastAPI 0.115.11+ et Pydantic 2.12.5+.

Premiers pas

Ce guide de démarrage rapide explique comment ajouter l’authentification Auth0 à une application Web FastAPI en Python. Vous créerez une application Web sécurisée avec des fonctionnalités de connexion, de déconnexion et de profil utilisateur à l’aide du Auth0 FastAPI SDK.
1

Créer un nouveau projet

Créez un nouveau répertoire pour votre projet, puis configurez un environnement virtuel :
mkdir auth0-fastapi-app && cd auth0-fastapi-app
Créez et activez un environnement virtuel :
python -m venv venv
source venv/bin/activate  # Sur Windows : venv\Scripts\activate
2

Installez le SDK FastAPI d’Auth0

pip install auth0-fastapi "uvicorn[standard]" python-dotenv itsdangerous
3

Configurez votre application Auth0

Ensuite, créez une nouvelle application sur votre locataire Auth0 et ajoutez les variables d’environnement à votre projet.Vous pouvez effectuer cette opération automatiquement en exécutant une commande CLI ou manuellement via le Auth0 Dashboard :
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 :
AUTH0_APP_NAME="My FastAPI App" && brew tap auth0/auth0-cli && brew install auth0 && auth0 login --no-input && auth0 apps create -n "${AUTH0_APP_NAME}" -t regular -c http://localhost:3000/auth/callback -l http://localhost:3000 -o http://localhost:3000 --reveal-secrets --json > auth0-app-details.json && CLIENT_ID=$(jq -r '.client_id' auth0-app-details.json) && CLIENT_SECRET=$(jq -r '.client_secret' auth0-app-details.json) && DOMAIN=$(auth0 tenants list --json | jq -r '.[] | select(.active == true) | .name') && SESSION_SECRET=$(openssl rand -hex 64) && echo "AUTH0_DOMAIN=${DOMAIN}" > .env && echo "AUTH0_CLIENT_ID=${CLIENT_ID}" >> .env && echo "AUTH0_CLIENT_SECRET=${CLIENT_SECRET}" >> .env && echo "SESSION_SECRET=${SESSION_SECRET}" >> .env && echo "APP_BASE_URL=http://localhost:3000" >> .env && rm auth0-app-details.json && echo ".env file created with your Auth0 details:" && cat .env
4

Configurer le SDK Auth0 pour FastAPI

Créez un fichier main.py à la racine de votre projet et ajoutez le code suivant :
main.py
import os
from fastapi import FastAPI, Depends, Request, Response
from starlette.middleware.sessions import SessionMiddleware
from dotenv import load_dotenv

from auth0_fastapi.config import Auth0Config
from auth0_fastapi.auth.auth_client import AuthClient
from auth0_fastapi.server.routes import router, register_auth_routes

# Charger les variables d'environnement
load_dotenv()

app = FastAPI(title="Auth0 FastAPI Example")

# Ajouter le middleware de session - requis pour la gestion des témoins
app.add_middleware(SessionMiddleware, secret_key=os.getenv("SESSION_SECRET"))

# Créer Auth0Config avec vos identifiants Auth0
config = Auth0Config(
    domain=os.getenv("AUTH0_DOMAIN"),
    client_id=os.getenv("AUTH0_CLIENT_ID"),
    client_secret=os.getenv("AUTH0_CLIENT_SECRET"),
    app_base_url=os.getenv("APP_BASE_URL", "http://localhost:3000"),
    secret=os.getenv("SESSION_SECRET"),
)

# Instancier le AuthClient
auth_client = AuthClient(config)

# Associer à l'état de l'application FastAPI
app.state.config = config
app.state.auth_client = auth_client

# Enregistrer les routes d'authentification
register_auth_routes(router, config)
app.include_router(router)
SESSION_SECRET sert à chiffrer les cookies de session et doit être cryptographiquement sûr. Sans secret robuste (au moins 32 octets), les sessions de votre application peuvent être compromises. Générez un secret sécurisé avec openssl rand -hex 64 et ne l’ajoutez jamais à votre système de gestion de versions.SessionMiddleware doit être ajouté avant d’utiliser le SDK. Sans lui, FastAPI ne peut ni lire ni définir de témoins, et toutes les tentatives d’authentification échoueront sans message d’erreur.HTTPS en production est requis pour les cookies sécurisés (secure=True). Sans HTTPS, les cookies de session ne seront pas envoyés par les navigateurs, et les utilisateurs seront déconnectés après chaque requête.
5

Créer des routes et afficher le profil utilisateur

Ajoutez les routes suivantes à votre fichier main.py pour créer une page d’accueil et une page de profil protégée :
main.py
import os
from fastapi import FastAPI, Depends, Request, Response
from fastapi.responses import HTMLResponse
from starlette.middleware.sessions import SessionMiddleware
from dotenv import load_dotenv

from auth0_fastapi.config import Auth0Config
from auth0_fastapi.auth.auth_client import AuthClient
from auth0_fastapi.server.routes import router, register_auth_routes

# Charger les variables d'environnement
load_dotenv()

app = FastAPI(title="Auth0 FastAPI Example")

# Ajouter le middleware de session - requis pour la gestion des témoins
app.add_middleware(SessionMiddleware, secret_key=os.getenv("SESSION_SECRET"))

# Créer Auth0Config avec vos identifiants Auth0
config = Auth0Config(
    domain=os.getenv("AUTH0_DOMAIN"),
    client_id=os.getenv("AUTH0_CLIENT_ID"),
    client_secret=os.getenv("AUTH0_CLIENT_SECRET"),
    app_base_url=os.getenv("APP_BASE_URL", "http://localhost:3000"),
    secret=os.getenv("SESSION_SECRET"),
    authorization_params={
      "scope": "openid profile email", # Requis pour obtenir les informations du profil utilisateur
    }
)

# Instancier le AuthClient
auth_client = AuthClient(config)

# Attacher à l'état de l'application FastAPI
app.state.config = config
app.state.auth_client = auth_client

# Enregistrer les routes d'authentification
register_auth_routes(router, config)
app.include_router(router)


@app.get("/", response_class=HTMLResponse)
async def home(request: Request, response: Response):
    """Home page with login/logout buttons"""
    store_options = {"request": request, "response": response}
    session = await auth_client.client.get_session(store_options=store_options)

    if session:
        user = await auth_client.client.get_user(store_options=store_options)
        return f"""
        <!DOCTYPE html>
        <html>
        <head>
            <title>Auth0 FastAPI Example</title>
            <style>
                body {{
                    font-family: 'Inter', system-ui, -apple-system, sans-serif;
                    background-color: #1a1e27;
                    color: #e2e8f0;
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    min-height: 100vh;
                    margin: 0;
                }}
                .container {{
                    background-color: #262a33;
                    border-radius: 20px;
                    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
                    padding: 3rem;
                    max-width: 500px;
                    width: 90%;
                    text-align: center;
                }}
                .logo {{
                    width: 160px;
                    margin-bottom: 1.5rem;
                }}
                h1 {{
                    font-size: 2.8rem;
                    font-weight: 700;
                    color: #f7fafc;
                    margin-bottom: 1rem;
                }}
                .success {{
                    font-size: 1.5rem;
                    color: #68d391;
                    font-weight: 600;
                    margin: 1.5rem 0;
                }}
                .profile {{
                    background-color: #2d313c;
                    border-radius: 15px;
                    padding: 2rem;
                    margin: 2rem 0;
                }}
                .profile-image {{
                    width: 110px;
                    height: 110px;
                    border-radius: 50%;
                    border: 3px solid #63b3ed;
                    margin-bottom: 1rem;
                }}
                .profile-name {{
                    font-size: 2rem;
                    font-weight: 600;
                    color: #f7fafc;
                    margin-bottom: 0.5rem;
                }}
                .profile-email {{
                    font-size: 1.15rem;
                    color: #a0aec0;
                }}
                .button {{
                    padding: 1.1rem 2.8rem;
                    font-size: 1.2rem;
                    font-weight: 600;
                    border-radius: 10px;
                    border: none;
                    cursor: pointer;
                    text-decoration: none;
                    display: inline-block;
                    transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
                    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
                    text-transform: uppercase;
                    letter-spacing: 0.08em;
                }}
                .button.logout {{
                    background-color: #fc8181;
                    color: #1a1e27;
                }}
                .button.logout:hover {{
                    background-color: #e53e3e;
                    transform: translateY(-5px) scale(1.03);
                    box-shadow: 0 12px 25px rgba(0, 0, 0, 0.5);
                }}
            </style>
        </head>
        <body>
            <div class="container">
                <img src="https://cdn.auth0.com/quantum-assets/dist/latest/logos/auth0/auth0-lockup-en-ondark.png"
                     alt="Auth0 Logo" class="logo">
                <h1>Welcome to Auth0 FastAPI</h1>
                <div class="success">✅ Successfully authenticated!</div>
                <h2>Your Profile</h2>
                <div class="profile">
                    <img src="{user.get('picture', '')}"
                         alt="{user.get('name', 'User')}" class="profile-image">
                    <div class="profile-name">{user.get('name', 'User')}</div>
                    <div class="profile-email">{user.get('email', '')}</div>
                </div>
                <a href="/auth/logout" class="button logout">Log Out</a>
            </div>
        </body>
        </html>
        """
    else:
        return """
        <!DOCTYPE html>
        <html>
        <head>
            <title>Auth0 FastAPI Example</title>
            <style>
                body {
                    font-family: 'Inter', system-ui, -apple-system, sans-serif;
                    background-color: #1a1e27;
                    color: #e2e8f0;
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    min-height: 100vh;
                    margin: 0;
                }
                .container {
                    background-color: #262a33;
                    border-radius: 20px;
                    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6);
                    padding: 3rem;
                    max-width: 500px;
                    width: 90%;
                    text-align: center;
                }
                .logo {
                    width: 160px;
                    margin-bottom: 1.5rem;
                }
                h1 {
                    font-size: 2.8rem;
                    font-weight: 700;
                    color: #f7fafc;
                    margin-bottom: 1rem;
                }
                .action-card {
                    background-color: #2d313c;
                    border-radius: 15px;
                    padding: 2.5rem;
                    margin-top: 2rem;
                }
                .action-text {
                    font-size: 1.25rem;
                    color: #cbd5e0;
                    margin-bottom: 1.8rem;
                }
                .button {
                    padding: 1.1rem 2.8rem;
                    font-size: 1.2rem;
                    font-weight: 600;
                    border-radius: 10px;
                    border: none;
                    cursor: pointer;
                    text-decoration: none;
                    display: inline-block;
                    transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
                    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
                    text-transform: uppercase;
                    letter-spacing: 0.08em;
                }
                .button.login {
                    background-color: #63b3ed;
                    color: #1a1e27;
                }
                .button.login:hover {
                    background-color: #4299e1;
                    transform: translateY(-5px) scale(1.03);
                    box-shadow: 0 12px 25px rgba(0, 0, 0, 0.5);
                }
            </style>
        </head>
        <body>
            <div class="container">
                <img src="https://cdn.auth0.com/quantum-assets/dist/latest/logos/auth0/auth0-lockup-en-ondark.png"
                     alt="Auth0 Logo" class="logo">
                <h1>Welcome to Auth0 FastAPI</h1>
                <div class="action-card">
                    <p class="action-text">Get started by signing in to your account</p>
                    <a href="/auth/login" class="button login">Log In</a>
                </div>
            </div>
        </body>
        </html>
        """


@app.get("/profile")
async def profile(
    request: Request,
    response: Response,
    session=Depends(auth_client.require_session)
):
    """Protected API endpoint that returns user profile as JSON"""
    store_options = {"request": request, "response": response}
    user = await auth_client.client.get_user(store_options=store_options)

    return {
        "message": "Your Profile",
        "user": user,
        "session_details": session
    }


if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=3000)
Cela crée :
  • Une page d’accueil (/) qui affiche un bouton de connexion lorsque l’utilisateur n’est pas connecté, ou son profil lorsqu’il est connecté
  • Un endpoint d’API protégé (/profile) qui renvoie des données utilisateur au format JSON et nécessite une authentification
  • Style complet pour une expérience utilisateur soignée
6

Exécutez votre application

uvicorn main:app --reload --port 3000
Sinon, si vous avez ajouté le bloc if __name__ == "__main__" dans votre fichier main.py :
python main.py
Point de contrôleVous devriez maintenant avoir une page de connexion Auth0 pleinement fonctionnelle qui s’exécute sur votre localhost.

Utilisation avancée

Créez des dépendances FastAPI personnalisées pour le contrôle d’accès basé sur les rôles :
from fastapi import Depends, HTTPException, status
from typing import List

async def require_roles(required_roles: List[str]):
    """Fabrique de dépendances pour le contrôle d’accès basé sur les rôles"""
    async def check_roles(
        request: Request,
        response: Response,
        session=Depends(auth_client.require_session)
    ):
        store_options = {"request": request, "response": response}
        user = await auth_client.client.get_user(store_options=store_options)

        user_roles = user.get("app_metadata", {}).get("roles", [])

        if not any(role in user_roles for role in required_roles):
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail=f"Required roles: {', '.join(required_roles)}"
            )

        return session

    return check_roles

# Utilisation dans les routes
@app.get("/admin/dashboard")
async def admin_dashboard(
    session=Depends(require_roles(["admin", "superadmin"]))
):
    return {"message": "Admin dashboard access granted"}

@app.delete("/admin/users/{user_id}")
async def delete_user(
    user_id: str,
    session=Depends(require_roles(["admin"]))
):
    return {"message": f"User {user_id} deleted"}
Configurez le SDK pour demander des jetons d’accès pour votre API et les utiliser dans les appels subséquents :
from auth0_fastapi.config import Auth0Config
import httpx

# Configurer Auth0 avec l’audience de l’API
config = Auth0Config(
    domain=os.getenv("AUTH0_DOMAIN"),
    client_id=os.getenv("AUTH0_CLIENT_ID"),
    client_secret=os.getenv("AUTH0_CLIENT_SECRET"),
    app_base_url=os.getenv("APP_BASE_URL"),
    secret=os.getenv("SESSION_SECRET"),
    audience="https://api.example.com",  # Votre identificateur d’API
    authorization_params={
        "scope": "openid profile email read:data write:data",
    },
)

@app.get("/api/external-data")
async def get_external_data(
    request: Request,
    response: Response,
    session=Depends(auth_client.require_session)
):
    """Appeler une API externe avec le jeton d’accès de l’utilisateur"""
    # Obtenir le jeton d’accès depuis la session
    access_token = session.get("access_token")

    if not access_token:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="No access token available"
        )

    # Effectuer un appel d’API authentifié
    async with httpx.AsyncClient() as client:
        api_response = await client.get(
            "https://api.example.com/data",
            headers={"Authorization": f"Bearer {access_token}"}
        )

        if api_response.status_code != 200:
            raise HTTPException(
                status_code=api_response.status_code,
                detail="External API call failed"
            )

    return {"data": api_response.json()}
Mettez votre application à l’échelle en stockant les sessions dans Redis plutôt que dans des témoins chiffrés :
from auth0_fastapi.stores.stateful_state_store import StatefulStateStore
from redis import asyncio as aioredis

# Créer le client Redis
redis = await aioredis.from_url(
    "redis://localhost:6379",
    encoding="utf-8",
    decode_responses=True
)

# Créer le magasin avec état
state_store = StatefulStateStore(
    secret=os.getenv("SESSION_SECRET"),
    store=redis,
    cookie_name="_session_id",
    expiration=86400,  # 1 jour en secondes
)

# Transmettre à AuthClient
auth_client = AuthClient(config, state_store=state_store)
Avantages des sessions avec état :
  • Aucune limite de taille des témoins - Stockez une quantité illimitée de données de session
  • Invalidation immédiate - Supprimez les sessions côté serveur
  • Prise en charge de la déconnexion backchannel - Gérez les événements de déconnexion provenant d’Auth0
  • Mieux adapté aux systèmes distribués - Partagez les sessions entre plusieurs serveurs

Dépannage

Problème : Les utilisateurs sont connectés, mais les sessions ne sont pas conservées d’une requête à l’autre.Causes possibles et solutions :
  1. SessionMiddleware manquant Assurez-vous d’avoir ajouté SessionMiddleware à votre application :
    from starlette.middleware.sessions import SessionMiddleware
    
    app.add_middleware(SessionMiddleware, secret_key=os.getenv("SESSION_SECRET"))
    
  2. HTTP en production avec des témoins sécurisés Les témoins sécurisés nécessitent HTTPS. Si vous faites des tests en local sur HTTP, vous pouvez désactiver temporairement les témoins sécurisés (non recommandé en production) :
    from auth0_fastapi.stores.stateless_state_store import StatelessStateStore
    
    state_store = StatelessStateStore(
        secret=config.secret,
        cookie_name="_a0_session",
        expiration=config.session_expiration
    )
    # Développement seulement!
    state_store.cookie_options["secure"] = False
    
    auth_client = AuthClient(config, state_store=state_store)
    
  3. SESSION_SECRET faible ou manquant Générez un secret robuste :
    openssl rand -hex 64
    
Problème : Après avoir cliqué sur “Log In”, Auth0 affiche l’erreur suivante : “Callback URL mismatch”Cause : L’URL de rappel n’est pas enregistrée dans les paramètres de votre application Auth0.Solution :
  1. Accédez à Auth0 Dashboard → Applications → Votre application → Settings
  2. Ajoutez votre URL de rappel à Allowed Callback URLs :
    http://localhost:3000/auth/callback
    
  3. Pour la production, ajoutez votre URL de production :
    https://yourdomain.com/auth/callback
    
  4. Cliquez sur Save Changes
Remarque : L’URL doit correspondre exactement, y compris le protocole (http/https) et le numéro de port.
Problème : Erreurs liées aux fonctions async ou aux boucles d’événements.Cause : FastAPI est un framework async, et toutes les méthodes du SDK doivent être attendues avec await.Solution : Assurez-vous que toutes les fonctions de route sont async et que les méthodes du SDK sont correctement attendues :
# ✅ Correct
@app.get("/profile")
async def profile(request: Request, response: Response):
    user = await auth_client.client.get_user(
        store_options={"request": request, "response": response}
    )
    return {"user": user}

# ❌ Incorrect - async manquant
@app.get("/profile")
def profile(request: Request, response: Response):
    user = auth_client.client.get_user(...)  # Cela échouera
    return {"user": user}

# ❌ Incorrect - await manquant
@app.get("/profile")
async def profile(request: Request, response: Response):
    user = auth_client.client.get_user(...)  # Retourne une coroutine, pas des données
    return {"user": user}
Problème : Les sessions fonctionnent en local, mais pas en production.Cause : Les témoins sécurisés nécessitent HTTPS en production. L’indicateur secure=True empêche l’envoi des témoins sur des connexions HTTP non chiffrées.Solution :
  1. Configurez HTTPS sur votre serveur de production à l’aide de :
    • certificats Let’s Encrypt
    • SSL/TLS du fournisseur infonuagique (AWS ALB, Cloudflare, etc.)
    • proxy inverse (Nginx, Caddy, Traefik)
  2. Mettez à jour les URL de votre application Auth0 pour utiliser HTTPS :
    https://yourdomain.com/auth/callback
    https://yourdomain.com
    
  3. Assurez-vous que APP_BASE_URL utilise HTTPS :
    APP_BASE_URL=https://yourdomain.com
    
Pour plus de fonctionnalités avancées et d’options de configuration, consultez la documentation du Auth0 FastAPI SDK.