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

# Protégez votre API Go

> Ce guide explique comment protéger les points de terminaison d’une API Go à l’aide de jetons d’accès JWT avec le SDK go-jwt-middleware v3.

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

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) + "*****MASQUÉ*****";
          }
          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>;
};

<HowToSchema />

export const envSnippet = `# L’URL du domaine de votre tenant Auth0.
# Si vous utilisez un domaine personnalisé, indiquez plutôt cette valeur.
AUTH0_DOMAIN='{yourDomain}'

# L’identifiant de votre API Auth0 (à l’étape 2)
# Exemple : https://my-go-api.example.com
AUTH0_AUDIENCE='{yourApiIdentifier}'`;

<Accordion title="Utilisez l’IA pour intégrer Auth0" icon="microchip-ai" iconType="solid" defaultOpen>
  Si vous utilisez un assistant IA de programmation comme Claude Code, Cursor ou GitHub Copilot, vous pouvez ajouter automatiquement l’authentification à l’Auth0 API en quelques minutes grâce à [Agent Skills](https://agentskills.io/home).

  **Installer :**

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

  **Ensuite, demandez à votre assistant IA :**

  ```text theme={null}
  Add Auth0 JWT authentication to my Go API
  ```

  Votre assistant IA créera automatiquement votre Auth0 API, récupérera les identifiants, installera `go-jwt-middleware`, configurera le validateur et protégera vos points de terminaison d’API à l’aide de la validation JWT. [Documentation complète d’Agent Skills →](/docs/fr-ca/quickstart/agent-skills)
</Accordion>

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

  * **[Go](https://go.dev/doc/install)** 1.24 ou une version ultérieure (requis pour la prise en charge des génériques dans go-jwt-middleware v3)
  * **[Git](https://git-scm.com/downloads)** pour le contrôle de version

  Vérifiez l’installation : `go version`
</Note>

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

Vous allez créer une API Go avec trois points de terminaison illustrant différents niveaux de protection : accès public, authentification par JWT et permissions à portée limitée. La mise en œuvre complète utilise [go-jwt-middleware v3](https://github.com/auth0/go-jwt-middleware) avec la bibliothèque standard `net/http` de Go.

<Card title="Voir l’exemple sur GitHub" href="https://github.com/auth0-samples/auth0-golang-api-samples/tree/master/01-Quickstart-Go-API" icon="github">
  Exemple complet fonctionnel avec tests
</Card>

<Steps>
  <Step title="Créer un nouveau projet" stepNumber={1}>
    Créez un nouveau dossier pour votre API en Go et initialisez un module.

    ```shellscript theme={null}
    mkdir myapi && cd myapi
    go mod init github.com/yourorg/myapi
    ```

    Installez les dépendances requises :

    ```shellscript theme={null}
    go get github.com/auth0/go-jwt-middleware/v3
    go get github.com/joho/godotenv
    go mod download
    ```

    Créez la structure du projet :

    ```shellscript theme={null}
    mkdir -p cmd/server internal/auth internal/config internal/handlers
    touch .env cmd/server/main.go internal/config/auth.go internal/auth/claims.go internal/auth/validator.go internal/auth/middleware.go internal/handlers/api.go
    ```

    <Accordion title="Voir le fichier go.mod attendu">
      ```go go.mod theme={null}
      module github.com/yourorg/myapi

      go 1.24

      require (
          github.com/auth0/go-jwt-middleware/v3 v3.1.0
          github.com/joho/godotenv v1.5.1
      )
      ```
    </Accordion>
  </Step>

  <Step title="Configurez votre API Auth0" stepNumber={2}>
    Ensuite, vous devez créer une nouvelle API dans votre tenant Auth0 et ajouter les variables d’environnement à votre projet.

    Vous avez deux options pour configurer votre API Auth0 : utiliser une commande CLI ou la configurer manuellement dans le Dashboard :

    <Tabs>
      <Tab title="CLI">
        Exécutez la commande suivante dans le répertoire racine de votre projet pour créer une API 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

          # Créer une API Auth0
          auth0 apis create \
            --name "My Go API" \
            --identifier https://my-go-api.example.com
          ```

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

          # Créer une API Auth0
          auth0 apis create `
            --name "My Go API" `
            --identifier https://my-go-api.example.com
          ```
        </CodeGroup>

        Une fois l’API créée, copiez les valeurs **Identifier** et **Domain**, puis créez votre fichier `.env` :

        <AuthCodeBlock children={envSnippet} language="bash" />

        <Note>
          Cette commande va :

          1. Vérifier si vous êtes authentifié (et vous inviter à vous connecter au besoin)
          2. Créer une API Auth0 avec l’identifiant spécifié
          3. Afficher les détails de l’API, y compris le domaine et l’identifiant
        </Note>
      </Tab>

      <Tab title="Dashboard">
        1. Accédez au [Auth0 Dashboard](https://manage.auth0.com/dashboard/)
        2. Allez à **Applications** → **APIs** → **Create API**
        3. Entrez un nom pour votre API (par ex., "My Go API")
        4. Définissez l’**Identifier** (par ex., `https://my-go-api.example.com`)
           * Il s’agit de l’audience de votre API et il doit respecter un format d’URL valide
           * Il n’a pas besoin d’être une vraie URL ; c’est simplement un identifiant
        5. Laissez **Signing Algorithm** à **RS256**
        6. Cliquez sur **Create**
        7. Copiez la valeur de l’**Identifier** depuis l’onglet **Settings**

        Créez votre fichier `.env` avec les valeurs suivantes :

        ```bash .env theme={null}
        AUTH0_DOMAIN=YOUR_AUTH0_DOMAIN
        AUTH0_AUDIENCE=YOUR_API_IDENTIFIER
        ```

        <Warning>
          Remplacez `YOUR_AUTH0_DOMAIN` par le domaine de votre tenant Auth0 (par ex., `dev-abc123.us.auth0.com`) et `YOUR_API_IDENTIFIER` par l’identifiant de votre API dans le dashboard (par ex., `https://my-go-api.example.com`).
        </Warning>
      </Tab>
    </Tabs>

    <Tip>
      **Sécurité** : N’envoyez jamais de fichiers `.env` dans le contrôle de version. Ajoutez `.env` à votre fichier `.gitignore`.
    </Tip>
  </Step>

  <Step title="Définir les permissions d’API" stepNumber={3}>
    Les permissions (scopes) vous permettent de définir comment les ressources peuvent être consultées. Par exemple, accordez l’accès `read` aux gestionnaires et l’accès `write` aux administrateurs.

    1. Dans les paramètres de votre API, cliquez sur l’onglet **Permissions**
    2. Créez la permission suivante :

    | Permission      | Description                |
    | --------------- | -------------------------- |
    | `read:messages` | Lire les messages de l’API |

    <Info>
      Ce tutoriel utilise le scope `read:messages` pour protéger le point de terminaison associé à cette portée. Vous pouvez définir des permissions supplémentaires selon les besoins de votre application.
    </Info>
  </Step>

  <Step title="Créer un chargeur de configuration" stepNumber={4}>
    Créez un package de configuration pour charger et valider des variables d’environnement.

    ```go internal/config/auth.go lines theme={null}
    package config

    import (
        "fmt"
        "os"
    )

    type AuthConfig struct {
        Domain   string
        Audience string
    }

    func LoadAuthConfig() (*AuthConfig, error) {
        domain := os.Getenv("AUTH0_DOMAIN")
        if domain == "" {
            return nil, fmt.Errorf("AUTH0_DOMAIN environment variable required")
        }

        audience := os.Getenv("AUTH0_AUDIENCE")
        if audience == "" {
            return nil, fmt.Errorf("AUTH0_AUDIENCE environment variable required")
        }

        return &AuthConfig{
            Domain:   domain,
            Audience: audience,
        }, nil
    }
    ```

    **Ce que cela fait :**

    * Charge le domaine Auth0 et l’audience à partir des variables d’environnement
    * Valide que la configuration requise est présente au démarrage
    * Renvoie une structure de configuration typée et sûre à utiliser dans toute l’application
  </Step>

  <Step title="Créer des revendications personnalisées et un validateur JWT" stepNumber={5}>
    Les claims personnalisées vous permettent d’extraire et de valider des données propres à l’application à partir de JWTs. Le validateur est le composant central qui vérifie les jetons auprès d’Auth0.

    <Tabs>
      <Tab title="claims.go">
        ```go internal/auth/claims.go lines theme={null}
        package auth

        import (
            "context"
            "fmt"
            "strings"
        )

        // CustomClaims contient les données personnalisées que nous voulons extraire du JWT.
        type CustomClaims struct {
            Scope string `json:"scope"`
        }

        // Validate s’assure que les claims personnalisées sont correctement formatées.
        func (c *CustomClaims) Validate(ctx context.Context) error {
            if c.Scope == "" {
                return nil
            }

            if strings.TrimSpace(c.Scope) != c.Scope {
                return fmt.Errorf("scope claim has invalid whitespace")
            }

            if strings.Contains(c.Scope, "  ") {
                return fmt.Errorf("scope claim contains double spaces")
            }

            return nil
        }

        // HasScope vérifie si nos claims contiennent une scope précise.
        func (c *CustomClaims) HasScope(expectedScope string) bool {
            if c.Scope == "" {
                return false
            }

            scopes := strings.Split(c.Scope, " ")
            for _, scope := range scopes {
                if scope == expectedScope {
                    return true
                }
            }
            return false
        }
        ```
      </Tab>

      <Tab title="validator.go">
        ```go internal/auth/validator.go lines theme={null}
        package auth

        import (
            "fmt"
            "net/url"
            "time"

            "github.com/auth0/go-jwt-middleware/v3/jwks"
            "github.com/auth0/go-jwt-middleware/v3/validator"
        )

        func NewValidator(domain, audience string) (*validator.Validator, error) {
            // Construire l’issuer URL (doit inclure la barre oblique finale)
            issuerURL, err := url.Parse("https://" + domain + "/")
            if err != nil {
                return nil, fmt.Errorf("failed to parse issuer URL: %w", err)
            }

            // Initialiser le fournisseur JWKS à l’aide du modèle d’options v3
            provider, err := jwks.NewCachingProvider(
                jwks.WithIssuerURL(issuerURL),
                jwks.WithCacheTTL(5*time.Minute),
            )
            if err != nil {
                return nil, fmt.Errorf("failed to create JWKS provider: %w", err)
            }

            // Créer le validateur à l’aide du modèle d’options v3
            jwtValidator, err := validator.New(
                validator.WithKeyFunc(provider.KeyFunc),
                validator.WithAlgorithm(validator.RS256),
                validator.WithIssuer(issuerURL.String()),
                validator.WithAudience(audience),
                validator.WithCustomClaims(func() validator.CustomClaims {
                    return &CustomClaims{}
                }),
                validator.WithAllowedClockSkew(30*time.Second),
            )
            if err != nil {
                return nil, fmt.Errorf("failed to create validator: %w", err)
            }

            return jwtValidator, nil
        }
        ```
      </Tab>
    </Tabs>

    **Points clés :**

    * La méthode `Validate` est appelée automatiquement par le middleware après l’analyse du JWT
    * `HasScope` analyse les scopes séparées par des espaces pour le contrôle d’accès basé sur les permissions
    * Le validateur utilise la mise en cache JWKS (TTL de 5 min) et tolère un décalage d’horloge de 30 s
    * L’algorithme RS256 est explicitement défini pour prévenir les [attaques de confusion d’algorithme](https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/)
  </Step>

  <Step title="Créer un middleware HTTP et des gestionnaires" stepNumber={6}>
    Le middleware encapsule le validateur pour les requêtes HTTP. Les handlers illustrent trois niveaux de protection : public, privé et protégé par permission.

    <Tabs>
      <Tab title="middleware.go">
        ```go internal/auth/middleware.go lines theme={null}
        package auth

        import (
            "log/slog"
            "net/http"

            jwtmiddleware "github.com/auth0/go-jwt-middleware/v3"
            "github.com/auth0/go-jwt-middleware/v3/validator"
        )

        func NewMiddleware(jwtValidator *validator.Validator) (*jwtmiddleware.JWTMiddleware, error) {
            return jwtmiddleware.New(
                jwtmiddleware.WithValidator(jwtValidator),
                jwtmiddleware.WithValidateOnOptions(false),
                jwtmiddleware.WithErrorHandler(func(w http.ResponseWriter, r *http.Request, err error) {
                    slog.Error("JWT validation failed", "error", err, "path", r.URL.Path)
                    w.Header().Set("Content-Type", "application/json")
                    w.WriteHeader(http.StatusUnauthorized)
                    w.Write([]byte(`{"message":"Failed to validate JWT."}`))
                }),
            )
        }
        ```
      </Tab>

      <Tab title="api.go">
        ```go internal/handlers/api.go expandable lines theme={null}
        package handlers

        import (
            "encoding/json"
            "net/http"

            "github.com/yourorg/myapi/internal/auth"
            jwtmiddleware "github.com/auth0/go-jwt-middleware/v3"
            "github.com/auth0/go-jwt-middleware/v3/validator"
        )

        // PublicHandler - aucune authentification requise
        func PublicHandler(w http.ResponseWriter, r *http.Request) {
            response := map[string]string{
                "message": "Hello from a public endpoint! You don't need to be authenticated to see this.",
            }
            w.Header().Set("Content-Type", "application/json")
            json.NewEncoder(w).Encode(response)
        }

        // PrivateHandler - nécessite un JWT valide
        func PrivateHandler(w http.ResponseWriter, r *http.Request) {
            response := map[string]string{
                "message": "Hello from a private endpoint! You need to be authenticated to see this.",
            }
            w.Header().Set("Content-Type", "application/json")
            json.NewEncoder(w).Encode(response)
        }

        // ScopedHandler - nécessite la permission 'read:messages'
        func ScopedHandler(w http.ResponseWriter, r *http.Request) {
            claims, err := jwtmiddleware.GetClaims[*validator.ValidatedClaims](r.Context())
            if err != nil {
                w.Header().Set("Content-Type", "application/json")
                w.WriteHeader(http.StatusUnauthorized)
                w.Write([]byte(`{"message":"Unauthorized."}`))
                return
            }

            customClaims, ok := claims.CustomClaims.(*auth.CustomClaims)
            if !ok || !customClaims.HasScope("read:messages") {
                w.Header().Set("Content-Type", "application/json")
                w.WriteHeader(http.StatusForbidden)
                w.Write([]byte(`{"message":"Insufficient scope."}`))
                return
            }

            response := map[string]string{
                "message": "Hello from a private endpoint! You need to be authenticated and have a scope of read:messages to see this.",
            }
            w.Header().Set("Content-Type", "application/json")
            json.NewEncoder(w).Encode(response)
        }
        ```
      </Tab>
    </Tabs>

    **Niveaux de protection :**

    * **Public** (`/api/public`) — Aucune authentification requise
    * **Privé** (`/api/private`) — JWT valide requis
    * **Avec permission** (`/api/private-scoped`) — JWT valide + permission `read:messages` requise
  </Step>

  <Step title="Créer le serveur principal" stepNumber={7}>
    Reliez le tout dans le point d’entrée principal avec des délais d’expiration prêts pour la production et un arrêt en douceur :

    ```go cmd/server/main.go expandable lines theme={null}
    package main

    import (
        "context"
        "log"
        "net/http"
        "os"
        "os/signal"
        "time"

        "github.com/yourorg/myapi/internal/auth"
        "github.com/yourorg/myapi/internal/config"
        "github.com/yourorg/myapi/internal/handlers"
        "github.com/joho/godotenv"
    )

    func main() {
        // Charger les variables d'environnement depuis le fichier .env
        if err := godotenv.Load(); err != nil {
            log.Println("No .env file found, using environment variables")
        }

        // Charger la configuration Auth0
        cfg, err := config.LoadAuthConfig()
        if err != nil {
            log.Fatalf("Failed to load config: %v", err)
        }

        // Créer le validateur JWT
        jwtValidator, err := auth.NewValidator(cfg.Domain, cfg.Audience)
        if err != nil {
            log.Fatalf("Failed to create validator: %v", err)
        }

        // Créer le middleware HTTP
        middleware, err := auth.NewMiddleware(jwtValidator)
        if err != nil {
            log.Fatalf("Failed to create middleware: %v", err)
        }

        // Configurer les routes
        mux := http.NewServeMux()
        mux.HandleFunc("/api/public", handlers.PublicHandler)
        mux.Handle("/api/private", middleware.CheckJWT(http.HandlerFunc(handlers.PrivateHandler)))
        mux.Handle("/api/private-scoped", middleware.CheckJWT(http.HandlerFunc(handlers.ScopedHandler)))

        // Configurer le serveur avec des délais d'expiration pour la production
        srv := &http.Server{
            Addr:         ":8080",
            Handler:      mux,
            ReadTimeout:  15 * time.Second,
            WriteTimeout: 15 * time.Second,
            IdleTimeout:  60 * time.Second,
        }

        // Démarrer le serveur dans une goroutine
        go func() {
            log.Println("Server starting on :8080")
            if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
                log.Fatalf("Server failed: %v", err)
            }
        }()

        // Arrêt gracieux
        quit := make(chan os.Signal, 1)
        signal.Notify(quit, os.Interrupt)
        <-quit

        log.Println("Shutting down server...")
        ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
        defer cancel()

        if err := srv.Shutdown(ctx); err != nil {
            log.Fatalf("Server forced to shutdown: %v", err)
        }

        log.Println("Server exited")
    }
    ```

    <Accordion title="Structure du projet">
      ```
      myapi/
      ├── cmd/
      │   └── server/
      │       └── main.go              # Point d’entrée de l’application
      ├── internal/
      │   ├── auth/
      │   │   ├── claims.go            # Claims JWT personnalisées
      │   │   ├── middleware.go         # Middleware JWT
      │   │   └── validator.go         # Validateur JWT
      │   ├── config/
      │   │   └── auth.go              # Chargement de la configuration
      │   └── handlers/
      │       └── api.go               # Gestionnaires HTTP (publics, privés, scopés)
      ├── .env                         # Variables d’environnement (non versionnées)
      ├── .gitignore
      ├── go.mod
      └── go.sum
      ```
    </Accordion>
  </Step>

  <Step title="Lancez et testez votre API" stepNumber={8}>
    Lancez le serveur de développement :

    ```shellscript theme={null}
    go run cmd/server/main.go
    ```

    Vous devriez voir : `Server starting on :8080`

    Testez le point de terminaison public (aucune authentification requise) :

    ```bash theme={null}
    curl http://localhost:8080/api/public
    ```

    Vous devriez voir :

    ```json theme={null}
    {
      "message": "Hello from a public endpoint! You don't need to be authenticated to see this."
    }
    ```

    Testez l’endpoint privé sans token (échec attendu) :

    ```bash theme={null}
    curl http://localhost:8080/api/private
    ```

    Vous devriez voir une erreur 401 Unauthorized :

    ```json theme={null}
    {
      "message": "Failed to validate JWT."
    }
    ```

    Pour tester avec un token valide, accédez à votre API dans le [Auth0 Dashboard](https://manage.auth0.com/#/apis), cliquez sur l’onglet **Test** et copiez l’access token. Exécutez ensuite :

    ```bash theme={null}
    curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
         http://localhost:8080/api/private
    ```

    Testez le point de terminaison à portée restreinte (nécessite l’autorisation `read:messages`) :

    ```bash theme={null}
    curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
         http://localhost:8080/api/private-scoped
    ```
  </Step>
</Steps>

<Check>
  **Vérification**

  Vous devriez maintenant disposer d’une API Go protégée. Votre API :

  1. Accepte les requêtes vers les points de terminaison publics sans authentification
  2. Rejette les requêtes vers les points de terminaison protégés sans jeton valide
  3. Valide les jetons JWT en fonction de votre domaine Auth0 et de votre audience
  4. Applique un contrôle d’accès basé sur les permissions à l’aide des scopes
</Check>

***

<div id="calling-your-api">
  ## Appeler votre API
</div>

Vous pouvez appeler votre API protégée à partir de n’importe quelle application en transmettant un jeton d’accès dans l’en-tête `Authorization` en tant que jeton Bearer.

<Accordion title="Exemples de code client" defaultOpen>
  <CodeGroup>
    ```bash cURL theme={null}
    curl --request GET \
      --url http://localhost:8080/api/private \
      --header 'authorization: Bearer YOUR_ACCESS_TOKEN'
    ```

    ```go Go theme={null}
    package main

    import (
        "fmt"
        "net/http"
        "io"
    )

    func main() {
        url := "http://localhost:8080/api/private"

        req, _ := http.NewRequest("GET", url, nil)
        req.Header.Add("authorization", "Bearer YOUR_ACCESS_TOKEN")

        res, _ := http.DefaultClient.Do(req)
        defer res.Body.Close()

        body, _ := io.ReadAll(res.Body)

        fmt.Println(res)
        fmt.Println(string(body))
    }
    ```

    ```javascript Node.js theme={null}
    const axios = require("axios").default;

    const options = {
      method: 'GET',
      url: 'http://localhost:8080/api/private',
      headers: {authorization: 'Bearer YOUR_ACCESS_TOKEN'}
    };

    axios.request(options).then(function (response) {
      console.log(response.data);
    }).catch(function (error) {
      console.error(error);
    });
    ```

    ```python Python theme={null}
    import http.client

    conn = http.client.HTTPConnection("localhost", 8080)
    headers = { 'authorization': "Bearer YOUR_ACCESS_TOKEN" }

    conn.request("GET", "/api/private", headers=headers)

    res = conn.getresponse()
    data = res.read()

    print(data.decode("utf-8"))
    ```
  </CodeGroup>
</Accordion>

<Accordion title="Obtenir un jeton d’accès">
  <Tabs>
    <Tab title="Applications monopages ou mobiles">
      Si vous appelez l’API à partir d’une Single-Page Application ou d’une application mobile/native, une fois le flux d’autorisation terminé, vous obtiendrez un jeton d’accès. La façon d’obtenir le jeton et d’effectuer la requête vers l’API dépend du type d’application que vous développez et du framework que vous utilisez.

      <CardGroup cols={2}>
        <Card title="Applications monopages" icon="browser" href="/docs/fr-ca/quickstart/spa">
          Quickstarts React, Vue et Angular avec exemples
        </Card>

        <Card title="Applications mobiles / natives" icon="mobile" href="/docs/fr-ca/quickstart/native">
          Quickstarts iOS, Android et React Native
        </Card>
      </CardGroup>
    </Tab>

    <Tab title="Machine-to-Machine (M2M)">
      Si vous appelez l’API à partir d’un outil en ligne de commande ou d’un autre service où aucun utilisateur ne saisit ses identifiants, vous devez utiliser le [flux OAuth Client Credentials](https://auth0.com/docs/api/authentication#client-credentials).

      <Steps>
        <Step title="Enregistrer une application M2M">
          Enregistrez une [Machine to Machine Application](https://manage.auth0.com/#/applications) dans votre Auth0 Dashboard.
        </Step>

        <Step title="Obtenir les identifiants">
          Copiez votre **Client ID** et votre **Client Secret** à partir des [Application Settings](https://auth0.com/docs/get-started/dashboard/application-settings).
        </Step>

        <Step title="Demander un jeton d’accès">
          Utilisez le flux Client Credentials pour obtenir un jeton d’accès :

          ```bash theme={null}
          curl --request POST \
            --url 'https://YOUR_AUTH0_DOMAIN/oauth/token' \
            --header 'content-type: application/x-www-form-urlencoded' \
            --data grant_type=client_credentials \
            --data 'client_id=YOUR_CLIENT_ID' \
            --data client_secret=YOUR_CLIENT_SECRET \
            --data audience=YOUR_API_IDENTIFIER
          ```
        </Step>
      </Steps>

      <Warning>
        **Réutilisation des jetons** : les clients d’Auth0 sont facturés en fonction du nombre de jetons d’accès Machine-to-Machine émis. Une fois que votre application a obtenu un jeton d’accès, elle devrait continuer à l’utiliser jusqu’à son expiration afin de réduire au minimum le nombre de jetons demandés.
      </Warning>
    </Tab>
  </Tabs>
</Accordion>

***

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

<Accordion title="Sécurité DPoP (Proof-of-Possession)">
  **DPoP (Demonstrating Proof-of-Possession)**, selon la RFC 9449, offre une sécurité renforcée en empêchant le vol de jeton grâce à l’association à une clé cryptographique.

  ```go internal/auth/middleware.go theme={null}
  func NewMiddleware(jwtValidator *validator.Validator) *jwtmiddleware.JWTMiddleware {
      return jwtmiddleware.New(
          jwtmiddleware.WithValidator(jwtValidator),
          jwtmiddleware.WithDPoPMode(jwtmiddleware.DPoPRequired),
          jwtmiddleware.WithLogger(slog.Default()),
      )
  }
  ```

  **Modes DPoP :**

  * `DPoPAllowed` (par défaut) — Accepte les jetons Bearer et DPoP
  * `DPoPRequired` — Accepte uniquement les jetons DPoP et rejette les jetons Bearer
  * `DPoPDisabled` — Accepte uniquement les jetons Bearer et rejette les jetons DPoP

  <Note>
    DPoP est recommandé pour les API financières, les API du secteur de la santé et les applications d’entreprise hautement sécurisées. Pour en savoir plus, consultez la [documentation DPoP](https://github.com/auth0/go-jwt-middleware#dpop-support).
  </Note>
</Accordion>

<Accordion title="Configuration CORS">
  Activez CORS pour autoriser les requêtes provenant d’applications web. Vous pouvez utiliser un middleware simple ou une bibliothèque comme [rs/cors](https://github.com/rs/cors) :

  ```bash theme={null}
  go get github.com/rs/cors
  ```

  ```go cmd/server/main.go theme={null}
  import "github.com/rs/cors"

  // Encapsuler le mux avec le middleware CORS
  handler := cors.New(cors.Options{
      AllowedOrigins:   []string{"http://localhost:3000"},
      AllowedMethods:   []string{"GET", "POST", "PUT", "DELETE"},
      AllowedHeaders:   []string{"Authorization", "Content-Type"},
      AllowCredentials: true,
  }).Handler(mux)

  srv := &http.Server{
      Addr:    ":8080",
      Handler: handler,
  }
  ```

  En production, indiquez des origines exactes au lieu d’utiliser des caractères génériques.
</Accordion>

<Accordion title="Journalisation structurée avec slog">
  Activez une journalisation détaillée pour déboguer la validation de jeton :

  ```go internal/auth/middleware.go theme={null}
  middleware := jwtmiddleware.New(
      jwtmiddleware.WithValidator(jwtValidator),
      jwtmiddleware.WithLogger(slog.Default()),
  )
  ```

  Ajoutez une vérification au démarrage :

  ```go cmd/server/main.go theme={null}
  log.Printf("Validator configured:")
  log.Printf("  Issuer: https://%s/", cfg.Domain)
  log.Printf("  Audience: %s", cfg.Audience)
  log.Printf("  Algorithm: RS256")
  ```
</Accordion>

***

<div id="troubleshooting">
  ## Dépannage
</div>

<AccordionGroup>
  <Accordion title="Problèmes courants et solutions">
    ### "Échec de la validation du JWT" ou 401 Unauthorized

    **Problème :** L’API ne parvient pas à trouver ou à valider le jeton d’accès.

    **Solutions :**

    1. Assurez-vous que l’en-tête `Authorization` est présent : `Authorization: Bearer YOUR_TOKEN`
    2. Vérifiez que "Bearer" figure bien avant le jeton
    3. Vérifiez que le jeton n’est pas expiré
    4. Assurez-vous d’utiliser un **jeton d’accès**, et non un ID token

    ### "incompatibilité de la claim aud"

    **Problème :** L’audience du jeton ne correspond pas à celle de votre API.

    **Solution :** Vérifiez que `AUTH0_AUDIENCE` correspond exactement à l’identificateur de votre API dans l’Auth0 Dashboard. L’audience ne doit PAS se terminer par une barre oblique :

    ```bash theme={null}
    # Correct
    AUTH0_AUDIENCE=https://my-go-api.example.com

    # Wrong (no trailing slash)
    AUTH0_AUDIENCE=https://my-go-api.example.com/
    ```

    L’application cliente doit aussi demander un jeton avec le bon paramètre d’audience.

    ### "méthode de signature inattendue"

    **Problème :** L’algorithme du jeton ne correspond pas à la configuration du validateur.

    **Solutions :**

    1. Auth0 utilise RS256 par défaut (asymétrique)
    2. Assurez-vous que votre validateur utilise `validator.RS256`
    3. N’utilisez jamais `validator.HS256` pour des jetons Auth0, sauf si cela a été configuré explicitement

    ### Point de terminaison JWKS inaccessible

    **Problème :** Le fournisseur de mise en cache JWKS ne parvient pas à joindre le point de terminaison de clé publique d’Auth0.

    **Solutions :**

    1. Vérifiez la connectivité réseau vers Auth0 (paramètres de pare-feu/proxy)
    2. Testez le point de terminaison JWKS manuellement : `curl https://YOUR_AUTH0_DOMAIN/.well-known/jwks.json`
    3. Vérifiez que la région Auth0 est correcte (us/eu/au)

    ### Chemin d’importation incorrect

    **Problème :** `cannot find package "github.com/auth0/go-jwt-middleware/v3/..."`

    **Solution :** Assurez-vous que toutes les importations utilisent le suffixe `/v3` :

    ```go theme={null}
    // Correct
    import "github.com/auth0/go-jwt-middleware/v3/validator"

    // Wrong
    import "github.com/auth0/go-jwt-middleware/validator"
    ```

    ### Erreurs liées au décalage d’horloge / jeton expiré

    **Problème :** L’horloge du serveur n’est pas synchronisée, ce qui fait paraître expirés des jetons valides.

    **Solution :** Le validateur inclut déjà une tolérance de 30 s pour le décalage d’horloge. Si vous avez besoin de plus, ajustez :

    ```go theme={null}
    validator.WithAllowedClockSkew(60*time.Second)
    ```

    ### Échec de l’extraction des claims

    **Problème :** `Failed to retrieve claims` lors de l’utilisation des génériques.

    **Solution :** Assurez-vous d’utiliser le bon paramètre de type :

    ```go theme={null}
    claims, err := jwtmiddleware.GetClaims[*validator.ValidatedClaims](r.Context())
    ```
  </Accordion>
</AccordionGroup>

***

<div id="next-steps">
  ## Prochaines étapes
</div>

Maintenant que vous disposez d’une API protégée, pensez à explorer :

* **[Contrôle d’accès basé sur les rôles](https://auth0.com/docs/manage-users/access-control/rbac)** — Mettez en place des permissions granulaires
* **[Bonnes pratiques pour les jetons d’accès](https://auth0.com/docs/secure/tokens/access-tokens)** — Découvrez la sécurité des jetons
* **[Surveillez votre API](https://auth0.com/docs/deploy-monitor/logs)** — Configurez la journalisation et la surveillance
* **[Vérifications de préparation à la production](https://auth0.com/docs/deploy-monitor/pre-deployment-checks/production-checks-best-practices)** — Vérification de sécurité avant le lancement

***

<div id="resources">
  ## Ressources
</div>

* **[go-jwt-middleware GitHub](https://github.com/auth0/go-jwt-middleware)** — Code source, exemples et prise en charge de DPoP
* **[Go API Sample](https://github.com/auth0-samples/auth0-golang-api-samples)** — Exemple complet fonctionnel
* **[Auth0 Community](https://community.auth0.com/)** — Obtenez de l’aide auprès de la communauté
