Exemple de Validation JWT en C#
⚠️ 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 de mettre en œuvre 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 C#.
PrérequisLien direct vers Prérequis
Installez les packages NuGet requis :
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="7.0.3" />
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="7.0.3" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.0.3" />
Exemple CompletLien direct vers Exemple Complet
using System;
using System.Text.Json;
using Microsoft.IdentityModel.Tokens;
using Microsoft.IdentityModel.JsonWebTokens;
using System.Security.Cryptography;
using System.IdentityModel.Tokens.Jwt;
namespace JwtValidator
{
public class Validator
{
private readonly JwtSecurityTokenHandler _tokenHandler;
private readonly TokenValidationParameters _validationParameters;
public Validator(string publicKeyJwks)
{
_tokenHandler = new JwtSecurityTokenHandler();
_validationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
ValidateLifetime = false, // apply your company policy
ValidateAudience = true,
ValidateIssuer = true,
ValidIssuer = "Rokt",
ValidAudience = "", // Empty string as per Rokt specification
ClockSkew = TimeSpan.FromMinutes(1) // Allow 1 minute clock skew for production
};
// Import JWKS
ImportFromJwks(publicKeyJwks);
}
public ReferralData ValidateReferralToken(string jwtToken)
{
var result = new ReferralData();
try
{
var principal = _tokenHandler.ValidateToken(jwtToken, _validationParameters, out var validatedToken);
if (principal == null)
{
result.ErrorMessage = "Token validation failed";
return result;
}
result.IsValid = true;
// Extract referral data from claims
if (long.TryParse(principal.FindFirst("cid")?.Value, out long campaignID))
result.CampaignID = campaignID;
if (long.TryParse(principal.FindFirst("crid")?.Value, out long creativeID))
result.CreativeID = creativeID;
// Handle RCLID - hex string directly
string? rclidValue = principal.FindFirst("rclid")?.Value;
if (!string.IsNullOrEmpty(rclidValue))
{
result.RCLID = rclidValue.ToLower();
}
// Extract issued at time
if (validatedToken is JwtSecurityToken jwt)
{
result.IssuedAt = jwt.IssuedAt;
}
return result;
}
catch (Exception ex)
{
result.ErrorMessage = ex.Message;
return result;
}
}
private void ImportFromJwks(string jwksJson)
{
try
{
if (string.IsNullOrEmpty(jwksJson))
throw new ArgumentException("JWKS JSON cannot be null or empty");
var jwks = JsonSerializer.Deserialize<JsonWebKeySet>(jwksJson);
if (jwks?.Keys?.Count > 0)
{
var jwk = jwks.Keys[0];
var parameters = new ECParameters
{
Curve = ECCurve.NamedCurves.nistP256,
Q = new ECPoint
{
X = Base64UrlEncoder.DecodeBytes(jwk.X),
Y = Base64UrlEncoder.DecodeBytes(jwk.Y)
}
};
if (!string.IsNullOrEmpty(jwk.D))
{
parameters.D = Base64UrlEncoder.DecodeBytes(jwk.D);
}
var ecdsa = ECDsa.Create(parameters);
_validationParameters.IssuerSigningKey = new ECDsaSecurityKey(ecdsa);
}
else
{
throw new ArgumentException("No valid keys found in JWKS");
}
}
catch (JsonException ex)
{
throw new ArgumentException($"Invalid JWKS format: {ex.Message}", ex);
}
}
public class ReferralData
{
public long? CampaignID { get; set; }
public long? CreativeID { get; set; }
public string? RCLID { get; set; }
public DateTime? IssuedAt { get; set; }
public bool IsValid { get; set; }
public string? ErrorMessage { get; set; }
}
private static async Task<string> DownloadAndCacheJWKS(string jwksUrl, string cacheFile)
{
// Check if cache file exists and is recent (less than 24 hours old)
if (File.Exists(cacheFile))
{
var fileInfo = new FileInfo(cacheFile);
if (DateTime.Now - fileInfo.LastWriteTime < TimeSpan.FromHours(24))
{
Console.WriteLine($"Using cached JWKS from: {cacheFile}");
return await File.ReadAllTextAsync(cacheFile);
}
}
// Download JWKS
Console.WriteLine($"Downloading JWKS from: {jwksUrl}");
using var client = new HttpClient();
var response = await client.GetAsync(jwksUrl);
response.EnsureSuccessStatusCode();
var jwksJson = await response.Content.ReadAsStringAsync();
// Cache the JWKS
try
{
await File.WriteAllTextAsync(cacheFile, jwksJson);
Console.WriteLine($"JWKS cached to: {cacheFile}");
}
catch (Exception ex)
{
Console.WriteLine($"Warning: failed to cache JWKS: {ex.Message}");
}
return jwksJson;
}
public static async Task Main(string[] args)
{
// Copy the test token from the Overview page
string sampleToken = "PASTE_TEST_TOKEN_HERE";
// JWKS endpoint URL
string jwksUrl = "https://public-api.rokt.com/.well-known/jwks.json";
string jwksCacheFile = "jwks_cache.json";
Console.WriteLine("=== C# JWT Validator ===");
Console.WriteLine($"Token: {sampleToken.Substring(0, Math.Min(50, sampleToken.Length))}...");
Console.WriteLine($"JWKS URL: {jwksUrl}");
Console.WriteLine();
// Download and cache JWKS
string jwksJson = await DownloadAndCacheJWKS(jwksUrl, jwksCacheFile);
Console.WriteLine("JWKS downloaded and cached successfully");
// Extract public key coordinates from JWKS
var jwks = JsonSerializer.Deserialize<JWKS>(jwksJson);
if (jwks?.Keys == null || jwks.Keys.Length == 0)
{
Console.WriteLine("❌ No keys found in JWKS");
return;
}
var key = jwks.Keys[0];
var validator = new Validator(jwksJson);
var result = validator.ValidateReferralToken(sampleToken);
if (result.IsValid)
{
Console.WriteLine("✅ Token validation successful!");
Console.WriteLine($"Campaign ID: {result.CampaignID}");
Console.WriteLine($"Creative ID: {result.CreativeID}");
Console.WriteLine($"RCLID: {result.RCLID}");
Console.WriteLine($"Issued At: {result.IssuedAt:yyyy-MM-dd HH:mm:ss} UTC");
}
else
{
Console.WriteLine($"❌ Token validation failed: {result.ErrorMessage}");
}
}
}
}
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
=== C# 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 05:10:01 UTC
Comment ExécuterLien direct vers Comment Exécuter
- Enregistrez le code dans
RoktJwtValidator.cs - Créez un nouveau projet .NET :
dotnet new console - Installez les dépendances :
dotnet add package Microsoft.IdentityModel.Tokens Microsoft.IdentityModel.JsonWebTokens System.IdentityModel.Tokens.Jwt - Exécutez :
dotnet run
Implémentation Alternative avec .csprojLien direct vers Implémentation Alternative avec .csproj
Créez un fichier .csproj :
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="7.0.3" />
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="7.0.3" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.0.3" />
</ItemGroup>
</Project>
RemarquesLien direct vers Remarques
-
La clé publique est récupérée depuis le point de terminaison JWKS de Rokt
-
L'exemple utilise l'algorithme ECDSA-256 (ES256) pour la vérification de la signature
-
Envisagez de mettre en cache la clé publique pour améliorer les performances
-
C# fournit d'excellentes bibliothèques cryptographiques via Microsoft.IdentityModel