Exemple de Validation JWT en Go
⚠️ Avis Important : Ceci est un exemple basique à des fins de démonstration uniquement. Pour une utilisation en production, veuillez rechercher et mettre en œuvre les meilleures pratiques spécifiques à votre pile logicielle, vos exigences de sécurité et votre environnement de déploiement. Suivez toujours les directives de sécurité de votre organisation et envisagez d'utiliser des bibliothèques et des frameworks JWT établis.
📝 Remarque : Cet exemple démontre le téléchargement de JWKS et la mise en cache de fichiers à des fins éducatives. Dans les environnements de production, vous pouvez choisir d'implémenter la gestion des clés JWKS différemment en fonction de votre infrastructure - comme en utilisant la gestion de la configuration, des variables d'environnement, ou votre stratégie de mise en cache préférée.
Cet exemple démontre comment valider les jetons JWT de Rokt en utilisant Go.
PrérequisLien direct vers Prérequis
Installez les paquets requis :
go get github.com/golang-jwt/jwt/v5
Exemple CompletLien direct vers Exemple Complet
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"log"
"math/big"
"net/http"
"os"
"strings"
"time"
"github.com/golang-jwt/jwt/v5"
)
// JWKS represents JSON Web Key Set structure
type JWKS struct {
Keys []JWK `json:"keys"`
}
// JWK represents JSON Web Key structure
type JWK struct {
Kid string `json:"kid"`
Kty string `json:"kty"`
Crv string `json:"crv"`
X string `json:"x"`
Y string `json:"y"`
}
// ReferralClaims represents the referral data in JWT claims
type ReferralClaims struct {
CampaignID string `json:"cid"`
CreativeID string `json:"crid"`
RCLID string `json:"rclid"`
jwt.RegisteredClaims
}
// ValidateReferralToken validates JWT token and extracts referral data
func ValidateReferralToken(jwtToken, jwksJson string) (*ReferralClaims, error) {
// Parse JWKS
var jwks JWKS
if err := json.Unmarshal([]byte(jwksJson), &jwks); err != nil {
return nil, fmt.Errorf("failed to parse JWKS: %v", err)
}
if len(jwks.Keys) == 0 {
return nil, fmt.Errorf("no keys found in JWKS")
}
// Get the first key (assuming single key for simplicity)
jwk := jwks.Keys[0]
// Decode base64url encoded coordinates
xBytes, err := base64.RawURLEncoding.DecodeString(jwk.X)
if err != nil {
return nil, fmt.Errorf("failed to decode X coordinate: %v", err)
}
yBytes, err := base64.RawURLEncoding.DecodeString(jwk.Y)
if err != nil {
return nil, fmt.Errorf("failed to decode Y coordinate: %v", err)
}
// Create ECDSA public key
publicKey := &ecdsa.PublicKey{
Curve: elliptic.P256(),
X: new(big.Int).SetBytes(xBytes),
Y: new(big.Int).SetBytes(yBytes),
}
// Parse and validate JWT token
token, err := jwt.ParseWithClaims(jwtToken, &ReferralClaims{}, func(token *jwt.Token) (interface{}, error) {
// Verify signing method
if _, ok := token.Method.(*jwt.SigningMethodECDSA); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
return publicKey, nil
}, jwt.WithLeeway(60*time.Second)) // Allow 1 minute clock skew
if err != nil {
return nil, fmt.Errorf("failed to parse JWT: %v", err)
}
if claims, ok := token.Claims.(*ReferralClaims); ok && token.Valid {
return claims, nil
}
return nil, fmt.Errorf("invalid token")
}
func downloadAndCacheJWKS(jwksURL, cacheFile string) (string, error) {
// Check if cache file exists and is recent (less than 24 hours old)
if info, err := os.Stat(cacheFile); err == nil {
if time.Since(info.ModTime()) < 24*time.Hour {
fmt.Printf("Using cached JWKS from: %s\n", cacheFile)
data, err := os.ReadFile(cacheFile)
if err != nil {
return "", fmt.Errorf("failed to read cache file: %v", err)
}
return string(data), nil
}
}
// Download JWKS
fmt.Printf("Downloading JWKS from: %s\n", jwksURL)
resp, err := http.Get(jwksURL)
if err != nil {
return "", fmt.Errorf("failed to download JWKS: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("failed to download JWKS: HTTP %d", resp.StatusCode)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("failed to read response body: %v", err)
}
// Cache the JWKS
if err := os.WriteFile(cacheFile, body, 0644); err != nil {
fmt.Printf("Warning: failed to cache JWKS: %v\n", err)
} else {
fmt.Printf("JWKS cached to: %s\n", cacheFile)
}
return string(body), nil
}
func main() {
// Sample JWT token from Rokt
// Copy the test token from the Overview page
sampleToken := "PASTE_TEST_TOKEN_HERE"
// JWKS endpoint URL
jwksURL := "https://public-api.rokt.com/.well-known/jwks.json"
jwksCacheFile := "jwks_cache.json"
fmt.Println("=== Go JWT Validator ===")
fmt.Printf("Token: %s...\n", sampleToken[:50])
fmt.Printf("JWKS URL: %s\n", jwksURL)
fmt.Println()
// Download and cache JWKS
jwksJson, err := downloadAndCacheJWKS(jwksURL, jwksCacheFile)
if err != nil {
fmt.Printf("❌ Failed to download JWKS: %v\n", err)
return
}
fmt.Println("JWKS downloaded and cached successfully")
// Extract public key coordinates from JWKS
var jwks JWKS
if err := json.Unmarshal([]byte(jwksJson), &jwks); err != nil {
fmt.Printf("❌ Failed to parse JWKS: %v\n", err)
return
}
if len(jwks.Keys) == 0 {
fmt.Println("❌ No keys found in JWKS")
return
}
key := jwks.Keys[0]
// Validate the token
claims, err := ValidateReferralToken(sampleToken, jwksJson)
if err != nil {
log.Fatalf("Token validation failed: %v", err)
}
fmt.Println("✅ Token validation successful!")
fmt.Printf("Campaign ID: %s\n", claims.CampaignID)
fmt.Printf("Creative ID: %s\n", claims.CreativeID)
fmt.Printf("RCLID: %s\n", claims.RCLID)
fmt.Printf("Issued At: %v\n", claims.IssuedAt)
}
Exemple d'Entrée/SortieLien direct vers Exemple d'Entrée/Sortie
EntréeLien direct vers Entrée
- Jeton JWT : Copiez le jeton de test depuis la page d'aperçu
- Source de la Clé Publique :
https://public-api.rokt.com/.well-known/jwks.json
SortieLien direct vers Sortie
=== Go JWT Validator ===
Token: eyJhbGciOiJFUzI1NiIsImtpZCI6InJva3Qtc2lnbmluZy1rZXkiLCJ0eXAiOiJKV1QifQ...
JWKS URL: https://public-api.rokt.com/.well-known/jwks.json
Downloading JWKS from: https://public-api.rokt.com/.well-known/jwks.json
JWKS cached to: jwks_cache.json
JWKS downloaded and cached successfully
✅ Token validation successful!
Campaign ID: 3436085368692408324
Creative ID: 3437732754935906308
RCLID: 7db958dbd232247a4a8285a34d22fe0f4e9affa463bf5ee54e26721ab0df0e23
Issued At: 2025-08-20 15:10:01 +1000 AEST
Comment ExécuterLien direct vers Comment Exécuter
- Enregistrez le code dans
rokt_jwt_validator.go - Installez les dépendances :
go mod init rokt-validator && go get github.com/golang-jwt/jwt/v5 - Exécutez :
go run rokt_jwt_validator.go
Implémentation Alternative avec go.modLien direct vers Implémentation Alternative avec go.mod
Créez un fichier go.mod :
module rokt-validator
go 1.21
require github.com/golang-jwt/jwt/v5 v5.0.0
RemarquesLien direct vers Remarques
-
La clé publique est récupérée à partir du point de terminaison JWKS de Rokt
-
L'exemple utilise l'algorithme ECDSA-256 (ES256) pour la vérification de signature
-
Envisagez de mettre en cache la clé publique pour des raisons de performance
-
La bibliothèque standard de Go offre un excellent support cryptographique