Passer au contenu principal

Utiliser l’IA pour intégrer Auth0

Si vous utilisez un assistant IA de codage comme Claude Code, Cursor ou GitHub Copilot, vous pouvez ajouter automatiquement l’authentification Auth0 à votre API en quelques minutes à l’aide des agent skills.Installation :
npx skills add auth0/agent-skills --skill auth0-quickstart --skill go-jwt-middleware
Demandez ensuite à votre assistant IA :
Ajouter l’authentification JWT Auth0 à mon API Go
Votre assistant IA créera automatiquement votre API Auth0, récupérera les identifiants, installera go-jwt-middleware, configurera le validateur et protégera les points de terminaison de votre API en validant les JWT. Documentation complète sur les agent skills →
Prérequis : Avant de commencer, assurez-vous d’avoir installé ce qui suit :
  • Go 1.24 ou une version plus récente (requis pour la prise en charge des génériques dans go-jwt-middleware v3)
  • Git pour le contrôle de version
Vérifiez l’installation : go version

Premiers pas

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 protection fondée sur les permissions. L’implémentation complète utilise go-jwt-middleware v3 avec la bibliothèque standard net/http de Go.

Voir l’exemple sur GitHub

Exemple complet prêt à l’emploi avec tests
1

Créer un nouveau projet

Créez un nouveau répertoire pour votre API Go et initialisez un module.
mkdir myapi && cd myapi
go mod init github.com/yourorg/myapi
Installez les dépendances requises :
go get github.com/auth0/go-jwt-middleware/v3
go get github.com/joho/godotenv
go mod download
Créez la structure du projet :
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
go.mod
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
)
2

Configurez votre API Auth0

Ensuite, vous devez créer une nouvelle API dans votre locataire Auth0 et ajouter les variables d’environnement à votre projet.Vous avez deux options pour configurer votre API Auth0 : utiliser une commande CLI ou effectuer la configuration manuellement dans l’Auth0 Dashboard :
Exécutez la commande suivante à la racine de votre projet pour créer une API Auth0 :
# Installer Auth0 CLI (si ce n’est pas déjà fait)
brew tap auth0/auth0-cli && brew install auth0

# Créer l’API Auth0
auth0 apis create \
  --name "My Go API" \
  --identifier https://my-go-api.example.com
Après la création, copiez les valeurs Identifier et Domaine, puis créez votre fichier .env :
Cette commande permet de :
  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
Sécurité : ne validez jamais les fichiers .env dans votre système de contrôle de version. Ajoutez .env à votre fichier .gitignore.
3

Définir les permissions de l’API

Les autorisations (scopes) vous permettent de définir comment les ressources sont accessibles. Par exemple, accordez l’autorisation read aux gestionnaires et l’autorisation write aux administrateurs.
  1. Dans les paramètres de votre API, cliquez sur l’onglet Permissions
  2. Créez l’autorisation suivante :
AutorisationDescription
read:messagesLire les messages à partir de l’API
Ce tutoriel utilise le scope read:messages pour protéger le point de terminaison protégé par un scope. Vous pouvez définir des autorisations supplémentaires selon les besoins de votre application.
4

Créer un chargeur de configuration

Créez un module de configuration pour charger et valider les variables d’environnement.
internal/config/auth.go
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
  • Vérifie au démarrage que la configuration requise est présente
  • Retourne une structure de configuration typée pouvant être utilisée dans toute l’application
5

Créer des claims personnalisés et un validateur JWT

Les claims personnalisés vous permettent d’extraire et de valider des données propres à l’application à partir de JWT. Le validateur est le composant central qui vérifie les jetons auprès d’Auth0.
internal/auth/claims.go
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és sont correctement formatés.
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 un scope précis.
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
}
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és par des espaces pour le contrôle d’accès basé sur les autorisations
  • Le validateur utilise la mise en cache JWKS (TTL de 5 min) et autorise un décalage d’horloge de 30 s
  • L’algorithme RS256 est défini explicitement pour prévenir les attaques de confusion d’algorithme
6

Créer des middleware et des gestionnaires HTTP

L’intergiciel encapsule le validateur des requêtes HTTP. Les gestionnaires illustrent trois niveaux de protection : public, privé et avec scope d’autorisation.
internal/auth/middleware.go
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."}`))
        }),
    )
}
Niveaux de protection :
  • Public (/api/public) — Aucune authentification requise
  • Privé (/api/private) — JWT valide requis
  • Avec scope (/api/private-scoped) — JWT valide + permission read:messages requise
7

Créer le serveur principal

Assemblez le tout au point d’entrée principal avec des délais d’expiration adaptés à la production et un arrêt propre :
cmd/server/main.go
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() {
    // Load environment variables from .env file
    if err := godotenv.Load(); err != nil {
        log.Println("No .env file found, using environment variables")
    }

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

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

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

    // Setup 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 les 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,
    }

    // Start server in goroutine
    go func() {
        log.Println("Server starting on :8080")
        if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
            log.Fatalf("Server failed: %v", err)
        }
    }()

    // Graceful shutdown
    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")
}
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              # Chargeur de configuration
│   └── handlers/
│       └── api.go               # Gestionnaires HTTP (public, privé, avec scope)
├── .env                         # Variables d’environnement (non validées dans le dépôt)
├── .gitignore
├── go.mod
└── go.sum
8

Lancez et testez votre API

Démarrez le serveur de développement :
go run cmd/server/main.go
Vous devriez voir : Server starting on :8080Testez le point de terminaison public (aucune authentification requise) :
curl http://localhost:8080/api/public
Vous devriez voir :
{
  "message": "Hello from a public endpoint! You don't need to be authenticated to see this."
}
Testez le point de terminaison privé sans Token (échec attendu) :
curl http://localhost:8080/api/private
Vous devriez voir une erreur 401 « Unauthorized » :
{
  "message": "Failed to validate JWT."
}
Pour tester avec un jeton valide, accédez à votre API dans le Auth0 Dashboard, cliquez sur l’onglet Test et copiez le jeton d’accès. Exécutez ensuite :
curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
     http://localhost:8080/api/private
Testez le point de terminaison protégé par un scope (nécessite l’autorisation read:messages) :
curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
     http://localhost:8080/api/private-scoped
VérificationVous devriez maintenant disposer d’une API Go protégée. Votre API :
  1. Accepte les requêtes vers des points de terminaison publics sans authentification
  2. Rejette les requêtes vers des 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 autorisations à l’aide des scopes

Appeler votre API

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 sous forme de jeton Bearer.

Exemples de code d’application

curl --request GET \
  --url http://localhost:8080/api/private \
  --header 'authorization: Bearer YOUR_ACCESS_TOKEN'
Si vous appelez l’API à partir d’une application monopage ou d’une application mobile/native, vous obtiendrez un jeton d’accès une fois le flux d’autorisation terminé. La façon dont vous obtenez le jeton et appelez l’API dépend du type d’application que vous développez et du framework que vous utilisez.

Applications monopages

Guides de démarrage rapide React, Vue et Angular avec exemples

Applications mobiles / natives

Guides de démarrage rapide iOS, Android et React Native

Utilisation avancée

DPoP (démonstration de preuve de possession), conformément à la RFC 9449, offre une sécurité renforcée en empêchant le vol de jetons grâce à l’association cryptographique à une clé.
internal/auth/middleware.go
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 à la fois 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
DPoP est recommandé pour les API financières, les API du secteur de la santé et les applications d’entreprise à sécurité élevée. Pour en savoir plus, consultez la documentation DPoP.
Activez CORS pour autoriser les requêtes provenant d’applications web. Vous pouvez utiliser un middleware simple ou une bibliothèque comme rs/cors :
go get github.com/rs/cors
cmd/server/main.go
import "github.com/rs/cors"

// Wrap the mux with CORS middleware
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 précises au lieu d’utiliser des jokers.
Activez une journalisation détaillée pour faciliter le débogage de la validation des jetons :
internal/auth/middleware.go
middleware := jwtmiddleware.New(
    jwtmiddleware.WithValidator(jwtValidator),
    jwtmiddleware.WithLogger(slog.Default()),
)
Ajoutez une vérification au démarrage :
cmd/server/main.go
log.Printf("Validator configured:")
log.Printf("  Issuer: https://%s/", cfg.Domain)
log.Printf("  Audience: %s", cfg.Audience)
log.Printf("  Algorithm: RS256")

Dépannage

”Failed to validate 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 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 jeton d’identité

”aud claim mismatch”

Problème : L’audience du jeton ne correspond pas à votre API.Solution : Vérifiez que AUTH0_AUDIENCE correspond exactement à l’identifiant de votre API dans l’Auth0 Dashboard. L’audience ne doit PAS se terminer par une barre oblique :
# Correct
AUTH0_AUDIENCE=https://my-go-api.example.com

# Wrong (barre oblique finale)
AUTH0_AUDIENCE=https://my-go-api.example.com/
L’application cliente doit aussi demander un jeton avec le bon paramètre audience.

”unexpected signing method”

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 spécifie validator.RS256
  3. N’utilisez jamais validator.HS256 pour les jetons Auth0, sauf si cela a été configuré explicitement

Point de terminaison JWKS inaccessible

Problème : Le fournisseur de mise en cache JWKS ne peut 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 manuellement le point de terminaison JWKS : curl https://YOUR_AUTH0_DOMAIN/.well-known/jwks.json
  3. Vérifiez que vous utilisez la bonne région Auth0 (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 :
// Correct
import "github.com/auth0/go-jwt-middleware/v3/validator"

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

Décalage d’horloge / erreurs de 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-la :
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 :
claims, err := jwtmiddleware.GetClaims[*validator.ValidatedClaims](r.Context())

Prochaines étapes

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

Ressources