Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
La mise en cache des jetons améliore les performances, la fiabilité et l’expérience utilisateur des applications. Microsoft. Identity.Web fournit des stratégies de mise en cache flexibles qui équilibrent les performances, la persistance et la fiabilité opérationnelle.
Aperçu
Cette section décrit les jetons Microsoft. Identity.Web met en cache et pourquoi la mise en cache est importante pour votre application.
Quels jetons sont mis en cache ?
Microsoft. Identity.Web met en cache plusieurs types de jetons :
| Type de jeton | Taille | Étendue | Expulsion |
|---|---|---|---|
| Jetons d’accès | ~2 kB | Par (utilisateur/application, tenant, ressource) | Automatique (basé sur la durée de vie) |
| Actualiser les jetons | Variable | Par compte d’utilisateur | Manuel ou basé sur des stratégies |
| Jetons d’ID | ~2 à 7 Ko | Par utilisateur | Automatique |
Où la mise en cache des jetons s’applique :
- Applications web appelant des API - Jetons utilisateur pour l’accès délégué
- API web appelant des API en aval - Jetons OBO (nécessite des stratégies d’éviction minutieuses)
- Applications démon - Jetons d’application uniquement pour les appels de service à service
Pourquoi les jetons de cache ?
Avantages en matière de performances :
- Réduit les allers-retours à Microsoft Entra ID
- Appels d’API plus rapides (L1 : <10 ms vs L2 : ~30 ms vs network : >100 ms)
- Latence inférieure pour les utilisateurs finaux
Avantages de fiabilité :
- Continue de travailler pendant les pannes temporaires de Microsoft Entra
- Résilient aux transitoires de réseau
- Dégradation progressive en cas d’échec du cache distribué
Avantages des coûts :
- Réduit les demandes d’authentification (limitation de l’évitement)
- Réduire les coûts de Azure pour les opérations d’authentification
Démarrage rapide
Commencez rapidement avec l’une des configurations de cache suivantes, en fonction de votre environnement.
Développement - Cache en mémoire
L’exemple suivant ajoute un cache de jetons en mémoire, adapté au développement et aux exemples :
using Microsoft.Identity.Web;
builder.Services.AddMicrosoftIdentityWebAppAuthentication(builder.Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
Avantages :
- Simplicité de la configuration
- Performances rapides
- Aucune dépendance externe
Inconvénients:
- Cache perdu lors du redémarrage de l’application. Dans une application web, les utilisateurs restent connectés via le cookie, mais doivent se reconnecter pour obtenir un jeton d’accès et remplir à nouveau le cache
- Non adapté aux déploiements multiserveurs de production
- Non partagé entre les instances d’application
Production - Cache distribué
Pour les applications de production, en particulier les déploiements multiserveurs, utilisez un cache distribué sauvegardé par Redis ou un autre fournisseur :
using Microsoft.Identity.Web;
builder.Services.AddMicrosoftIdentityWebAppAuthentication(builder.Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDistributedTokenCaches();
// Choose your cache implementation
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = builder.Configuration.GetConnectionString("Redis");
options.InstanceName = "MyApp_";
});
Avantages :
- Résiste aux redémarrages de l'application
- Partagé entre toutes les instances d’application
- Mise en cache automatique L1+L2
Inconvénients:
- Nécessite une infrastructure de cache externe
- Complexité supplémentaire de la configuration
- Latence réseau pour les opérations de cache
Choix d’une stratégie de cache
Utilisez l’organigramme de décision et la matrice suivants pour sélectionner la stratégie de cache qui correspond le mieux à votre déploiement.
flowchart TD
Start([Token Caching<br/>Decision]) --> Q1{Production<br/>Environment?}
Q1 -->|No - Dev/Test| DevChoice[In-Memory Cache<br/>AddInMemoryTokenCaches]
Q1 -->|Yes| Q2{Multiple Server<br/>Instances?}
Q2 -->|No - Single Server| Q3{App Restarts<br/>Acceptable?}
Q3 -->|Yes| DevChoice
Q3 -->|No| DistChoice
Q2 -->|Yes| DistChoice[Distributed Cache<br/>AddDistributedTokenCaches]
DistChoice --> Q4{Cache<br/>Implementation?}
Q4 -->|High Performance| Redis[Redis Cache<br/>StackExchange.Redis<br/>⭐ Recommended]
Q4 -->|Azure Native| Azure[Azure Cache for Redis,<br/>Azure Cosmos DB,<br/>or Azure Database for PostgreSQL]
Q4 -->|On-Premises| SQL[SQL Server Cache<br/>AddDistributedSqlServerCache]
Q4 -->|Testing| DistMem[Distributed Memory<br/>Not for production]
Redis --> L1L2[Automatic L1+L2<br/>Caching]
Azure --> L1L2
SQL --> L1L2
DistMem --> L1L2
L1L2 --> Config[Configure Options<br/>MsalDistributedTokenCacheAdapterOptions]
DevChoice --> MemConfig[Configure Memory Options<br/>MsalMemoryTokenCacheOptions]
style Start fill:#e1f5ff
style DevChoice fill:#d4edda
style DistChoice fill:#fff3cd
style Redis fill:#d1ecf1
style L1L2 fill:#f8d7da
Matrice décisionnelle
Le tableau suivant récapitule les types de cache recommandés pour les scénarios de déploiement courants.
| Scénario | Cache recommandé | Justification |
|---|---|---|
| Développement local | In-Memory | Simplicité, aucune infrastructure n’est nécessaire |
| Exemples/démonstrations | In-Memory | Configuration facile pour les démonstrations |
| Production à serveur unique (redémarre OK) | In-Memory | Acceptable si les sessions peuvent être rétablies |
| Production multiserveur | Redis | Cache partagé, hautes performances, fiable |
| applications hébergées Azure | Azure Cache pour Redis | Intégration Azure native, service managé |
| Entreprise locale | SQL Server | Tire parti de l’infrastructure existante |
| Environnements PostgreSQL | PostgreSQL | Utilise une base de données PostgreSQL existante, sémantique SQL familière |
| Environnements haute sécurité | SQL Server + Chiffrement | Résidence des données, chiffrement au repos |
| Test de scénarios distribués | Mémoire distribuée | Teste le comportement du cache L2 sans infrastructure |
Implémentations du cache
Microsoft. Identity.Web prend en charge plusieurs implémentations de cache. Choisissez celui qui correspond à vos exigences d’infrastructure et de disponibilité.
Cache en mémoire
Quand les utiliser :
- Développement et test
- Déploiements à serveur unique avec comportement de redémarrage acceptable
- Exemples et prototypes
Configuration:
Le code suivant inscrit le cache de jetons en mémoire avec les paramètres par défaut :
builder.Services.AddMicrosoftIdentityWebAppAuthentication(builder.Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
Avec les options personnalisées :
Vous pouvez personnaliser les limites d’expiration et de taille en passant des options :
builder.Services.AddMicrosoftIdentityWebAppAuthentication(builder.Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches(options =>
{
// Token cache entry will expire after this duration
options.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1);
// Limit cache size (default is unlimited)
options.SizeLimit = 500 * 1024 * 1024; // 500 MB
});
→ En savoir plus sur la configuration du cache en mémoire
Cache distribué (L2) avec prise en charge automatique de L1
Quand les utiliser :
- Déploiements multiserveurs de production
- Applications nécessitant une persistance du cache entre les redémarrages
- Scénarios de haute disponibilité
Caractéristique clé : Depuis Microsoft.Identity.Web v1.8.0, le cache distribué inclut automatiquement un cache L1 en mémoire pour les performances et la fiabilité.
Cache Redis (recommandé)
Ajoutez le chaîne de connexion Redis à appsettings.json :
{
"ConnectionStrings": {
"Redis": "localhost:6379"
}
}
Inscrivez ensuite le cache de jetons distribué et le fournisseur Redis dans Program.cs :
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.TokenCacheProviders.Distributed;
builder.Services.AddMicrosoftIdentityWebAppAuthentication(builder.Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDistributedTokenCaches();
// Redis cache implementation
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = builder.Configuration.GetConnectionString("Redis");
options.InstanceName = "MyApp_"; // Unique prefix per application
});
// Optional: Configure distributed cache behavior
builder.Services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
// Control L1 cache size
options.L1CacheOptions.SizeLimit = 500 * 1024 * 1024; // 500 MB
// Handle L2 cache failures gracefully
options.OnL2CacheFailure = (exception) =>
{
if (exception is StackExchange.Redis.RedisConnectionException)
{
// Log the failure
// Optionally attempt reconnection
return true; // Retry the operation
}
return false; // Don't retry
};
});
Azure Cache pour Redis
Pour utiliser Azure Cache pour Redis, inscrivez le cache auprès de votre Azure chaîne de connexion :
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = builder.Configuration.GetConnectionString("AzureRedis");
options.InstanceName = "MyApp_";
});
Format de la chaîne de connexion :
<cache-name>.redis.cache.windows.net:6380,password=<access-key>,ssl=True,abortConnect=False
cache de SQL Server
L’exemple suivant configure SQL Server en tant que back-end de cache distribué :
builder.Services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString = builder.Configuration.GetConnectionString("TokenCacheDb");
options.SchemaName = "dbo";
options.TableName = "TokenCache";
// Set expiration longer than access token lifetime (default 1 hour)
// This prevents cache entries from expiring before tokens
options.DefaultSlidingExpiration = TimeSpan.FromMinutes(90);
});
cache Azure Cosmos DB
L’exemple suivant configure Azure Cosmos DB en tant que back-end de cache distribué :
builder.Services.AddCosmosCache((CosmosCacheOptions options) =>
{
options.ContainerName = builder.Configuration["CosmosCache:ContainerName"];
options.DatabaseName = builder.Configuration["CosmosCache:DatabaseName"];
options.ClientBuilder = new CosmosClientBuilder(
builder.Configuration["CosmosCache:ConnectionString"]);
options.CreateIfNotExists = true;
});
Cache PostgreSQL
Nécessite le package NuGet Microsoft.Extensions.Caching.Postgres.
appsettings.json:
{
"ConnectionStrings": {
"PostgresCache": "Host=localhost;Database=mydb;Username=myuser;Password=mypassword"
},
"PostgresCache": {
"SchemaName": "public",
"TableName": "token_cache",
"CreateIfNotExists": true
}
}
Inscrivez ensuite le cache PostgreSQL dans Program.cs :
builder.Services.AddDistributedPostgresCache(options =>
{
options.ConnectionString = builder.Configuration.GetConnectionString("PostgresCache");
options.SchemaName = builder.Configuration["PostgresCache:SchemaName"];
options.TableName = builder.Configuration["PostgresCache:TableName"];
options.CreateIfNotExists = builder.Configuration.GetValue<bool>("PostgresCache:CreateIfNotExists");
options.DefaultSlidingExpiration = TimeSpan.FromMinutes(90);
});
→ En savoir plus sur la configuration du cache distribué
Cache de session (non recommandé)
Avertissement
La mise en cache basée sur une session présente des limitations significatives. Utilisez plutôt un cache distribué.
L’exemple suivant montre la mise en cache de jetons basée sur une session pour référence :
using Microsoft.Identity.Web.TokenCacheProviders.Session;
// In Program.cs
builder.Services.AddSession();
builder.Services.AddMicrosoftIdentityWebAppAuthentication(builder.Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi()
.AddSessionTokenCaches();
// In middleware pipeline
app.UseSession(); // Must be before UseAuthentication()
app.UseAuthentication();
app.UseAuthorization();
Limitations :
- Problèmes de taille des cookies - Les jetons d’ID volumineux avec de nombreuses revendications provoquent des problèmes
- Conflits de périmètre Scope - Impossible à utiliser avec un singleton
TokenAcquisition(par exemple, Microsoft Graph SDK) - Affinité de session requise - Ne fonctionne pas correctement dans les scénarios à charge équilibrée
- Non recommandé - Utiliser le cache distribué à la place
Configuration avancée
Ces options vous permettent d’affiner le comportement du cache pour les stratégies de performances, de sécurité et d’éviction.
Contrôle de cache L1
Le cache L1 (en mémoire) améliore les performances lorsque vous utilisez des caches distribués. Le code suivant configure la taille et le comportement du cache L1 :
builder.Services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
// Control L1 cache size (default: 500 MB)
options.L1CacheOptions.SizeLimit = 100 * 1024 * 1024; // 100 MB
// Disable L1 cache if session affinity is not available
// (forces all requests to use L2 cache for consistency)
options.DisableL1Cache = false;
});
Quand désactiver L1 :
- Aucune affinité de session dans l’équilibreur de charge
- Les utilisateurs fréquemment invités à entrer l’authentification multifacteur en raison de l’incohérence du cache
- Compromis : l’accès L2 est plus lent (~30 ms contre ~10 ms)
Stratégies d’éviction du cache
Les stratégies d’éviction contrôlent quand les jetons mis en cache sont supprimés. Le code suivant définit l’expiration absolue et glissante :
builder.Services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
// Absolute expiration (removed after this time, regardless of use)
options.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(72);
// Sliding expiration (renewed on each access)
options.SlidingExpiration = TimeSpan.FromHours(2);
});
Vous pouvez également configurer l’éviction via appsettings.json:
{
"TokenCacheOptions": {
"AbsoluteExpirationRelativeToNow": "72:00:00",
"SlidingExpiration": "02:00:00"
}
}
builder.Services.Configure<MsalDistributedTokenCacheAdapterOptions>(
builder.Configuration.GetSection("TokenCacheOptions"));
Recommendations:
- Définir l’expiration plus longue que la durée de vie des jetons (les jetons expirent généralement en 1 heure)
- Valeur par défaut : expiration glissante de 90 minutes
- Équilibre entre l’utilisation de la mémoire et l’expérience utilisateur
- Considérez : 72 heures absolues + 2 heures glissantes pour une expérience utilisateur correcte
→ En savoir plus sur les stratégies d’éviction du cache
Chiffrement au repos
Pour protéger les données de jeton sensibles dans les caches distribués, activez le chiffrement via ASP.NET Core Protection des données.
Une machine
Sur un seul ordinateur, activez le chiffrement avec le fournisseur de protection des données intégré :
builder.Services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
options.Encrypt = true; // Uses ASP.NET Core Data Protection
});
Systèmes distribués (plusieurs serveurs)
Important
Les systèmes distribués ne partagent pas les clés de chiffrement par défaut. Vous devez configurer le partage de clés :
Azure Key Vault (recommandé) :
Le code suivant conserve les clés pour Stockage Blob Azure et les protège avec Azure Key Vault :
using Microsoft.AspNetCore.DataProtection;
builder.Services.AddDataProtection()
.PersistKeysToAzureBlobStorage(new Uri(builder.Configuration["DataProtection:BlobUri"]))
.ProtectKeysWithAzureKeyVault(
new Uri(builder.Configuration["DataProtection:KeyIdentifier"]),
new DefaultAzureCredential());
Basé sur un certificat :
Le code suivant conserve les clés d’un partage de fichiers et les protège avec un certificat X.509 :
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\keys"))
.ProtectKeysWithCertificate(
new X509Certificate2("current.pfx", builder.Configuration["CertPassword"]))
.UnprotectKeysWithAnyCertificate(
new X509Certificate2("current.pfx", builder.Configuration["CertPassword"]),
new X509Certificate2("previous.pfx", builder.Configuration["PrevCertPassword"]));
→ En savoir plus sur le chiffrement et la protection des données
Considérations relatives aux performances du cache
Utilisez les estimations suivantes pour planifier la capacité de cache pour votre application.
Estimations de taille de jeton
| Type de jeton | Taille standard | Par | Remarques |
|---|---|---|---|
| Jetons d’application | ~2 kB | Locataire × Ressource | Évincé automatiquement |
| Jetons utilisateur | ~7 Ko | Utilisateur × Locataire × Ressource | Éviction manuelle nécessaire |
| Jetons d’actualisation | Variable | Utilisateur | Durée de vie longue |
Planification de la mémoire
Pour 500 utilisateurs simultanés appelant 3 API :
- Jetons utilisateur : 500 × 3 × 7 Ko = 10,5 Mo
- Avec surcharge : ~15-20 Mo
Pour 10 000 utilisateurs simultanés :
- Jetons utilisateur : 10 000 × 3 × 7 Ko = 210 Mo
- Avec surcharge : ~300-350 Mo
Recommandation: Définissez la limite de taille du cache L1 en fonction des utilisateurs simultanés attendus.
Bonnes pratiques
Suivez ces instructions pour garantir la mise en cache des jetons fiable et efficace.
Utiliser le cache distribué en production - Essentiel pour les déploiements multi-serveurs
Définir les limites de taille de cache appropriées - Empêcher la croissance de la mémoire illimitée
Configurer des stratégies d’éviction - Équilibrer l’utilisation de l’expérience utilisateur et de la mémoire
Activer le chiffrement pour les données sensibles - Protéger les jetons au repos
Surveiller l’intégrité du cache - Suivre les taux d’accès, les échecs et les performances
Gérer correctement les défaillances du cache L2 - Le cache L1 garantit la résilience
Tester le comportement du cache - Vérifier les scénarios de redémarrage et le basculement
N’utilisez pas le cache de mémoire distribuée en production - Non persistant ou distribué
N’utilisez pas le cache de session - Présente des limitations significatives
Ne définissez pas l’expiration plus courte que la durée de vie du jeton - Force la réauthentification inutile
N’oubliez pas le partage de clés de chiffrement : les systèmes distribués ont besoin de clés partagées