Los tokencacheproblemen op in Microsoft.Identity.Web.

Dit artikel helpt u bij het vaststellen en oplossen van problemen met tokencaches in Microsoft. Identity.Web. Problemen met tokencache kunnen verificatiefouten, verminderde prestaties of onverwachte aanmeldingsprompts veroorzaken. Voor een overzicht van hoe tokencaching werkt in Microsoft. Identity.Web, zie Token cache overview.

Vereiste voorwaarden

Controleer het volgende voordat u problemen oplost:

  • U gebruikt een ondersteunde versie van Microsoft. Identity.Web.
  • Uw toepassing heeft tokencaching geconfigureerd in Program.cs of Startup.cs.
  • U hebt toegang tot toepassingslogboeken en, indien van toepassing, uw gedistribueerde cache-infrastructuur.

Inschakelen van tokencache-logging en diagnostiek

Schakel gedetailleerde logboekregistratie in als uw eerste diagnostische stap. Microsoft. Identity.Web maakt gebruik van de ASP.NET Core logboekregistratie-infrastructuur en verzendt gebeurtenissen via de Microsoft Authentication Library (MSAL).

MSAL-logboekregistratie inschakelen

Stel het logboekniveau Debug in op voor identiteitsbibliotheken in uw appsettings.json:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.Identity.Web": "Debug",
      "Microsoft.IdentityModel": "Debug"
    }
  }
}

Abonneren op MSAL-cache-gebeurtenissen

Abonneer u op MSAL-token cache notificatie-evenementen voor het volgen van cache-treffers, missers en serialisatie-activiteiten.

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(Configuration)
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddDistributedTokenCaches();

services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
    options.OnL2CacheFailure = (ex) =>
    {
        logger.LogWarning(ex, "L2 cache failure encountered.");
        // Return true to allow the operation to continue despite the cache failure.
        // Return false to propagate the exception.
        return true;
    };
});

Metrische gegevens van cache bewaken

Houd voor productiebewaking de volgende belangrijke metrische gegevens bij:

  • Cachetreffersnelheid : een lage treffersnelheid geeft aan dat tokens niet worden opgehaald uit de cache.
  • L2-cachelatentie : hoge latentie stelt een gedistribueerde cacheconnectiviteit of prestatieprobleem voor.
  • Serialisatiefouten in cache : fouten tijdens lezen of schrijven geven aan dat beschadigingen of versies niet overeenkomen.
  • Geheugenverbruik : aanhoudende groei kan duiden op ontbrekend verwijderingsbeleid.

Fouten bij verbinding met gedistribueerde cache (L2)

Symptoom

Applicatielogboeken tonen verbindingstime-outfouten of intermitterende authenticatiefouten. Gebruikers ervaren aanmeldingsvertragingen en u ziet uitzonderingen zoals:

Microsoft.Extensions.Caching.StackExchangeRedis.RedisCache:
  StackExchange.Redis.RedisConnectionException: 
  No connection is active/available to service this operation.

Of voor SQL Server gedistribueerde cache:

Microsoft.Data.SqlClient.SqlException:
  A network-related or instance-specific error occurred while 
  establishing a connection to SQL Server.

Oorzaak

De gedistribueerde cache backing store (Redis of SQL Server) is onbereikbaar. Veelvoorkomende oorzaken zijn onder andere:

  • Onjuiste verbindingsreeks of verlopen toegangsreferenties.
  • Netwerkfirewallregels blokkeren de verbinding van de app-host.
  • De cacheservice is niet actief of ondergaat onderhoud.
  • SSL/TLS-configuratie komt niet overeen tussen de client en de cacheserver.

Diagnostische stappen

Volg deze stappen om de verbindingsfout te identificeren:

  1. Controleer de connectiviteit. Test vanaf de toepassingshost de verbinding met Redis of SQL Server met behulp van Test-NetConnection (PowerShell) of redis-cli.
  2. Controleer de verbindingstekenreeks. Controleer of de verbindingsreeks overeenkomt met de hostnaam, poort en referenties van de cacheserver.
  3. Controleer de firewallregels. Controleer in Azure of de app-service of het virtuele netwerk de cacheresource kan bereiken.
  4. Het controleren van de servicestatus. Controleer in de Azure-portal de status en metrische gegevens van uw Azure Cache voor Redis- of SQL Database-exemplaar.

Solution

Stap 1: Corrigeer de verbindingsreeks

Controleer de verbindingsreeks in uw appsettings.json:

{
  "ConnectionStrings": {
    "Redis": "your-redis-instance.redis.cache.windows.net:6380,password=your-access-key,ssl=True,abortConnect=False"
  }
}

Belangrijk

Stel abortConnect=False in de Redis-verbindingsreeks in. Met deze instelling kan de toepassing automatisch de verbinding herstellen na tijdelijke connectiviteitsfouten in plaats van direct een fout op te werpen.

Stap 2: Opnieuw proberen en tolerantie configureren

Configureer de OnL2CacheFailure callback zodat uw toepassing probleemloos verslechtert wanneer de gedistribueerde cache tijdelijk niet beschikbaar is:

services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
    options.OnL2CacheFailure = (ex) =>
    {
        // Log the failure for monitoring and alerting.
        logger.LogWarning(ex, "Distributed token cache is unavailable. " +
            "Falling back to in-memory cache.");
        return true; // Continue without the L2 cache.
    };

    // Set a timeout to avoid blocking the request pipeline.
    options.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(12);
});

Stap 3: Firewallregels openen

Als de toepassing wordt uitgevoerd in Azure App Service en de cache zich in een virtueel netwerk bevindt, voegt u de uitgaande IP-adressen van App Service toe aan de acceptatielijst van de cachefirewall.

Fouten met cachedeserialisatie

Symptoom

Nadat u Microsoft.Identity.Web of MSAL.NET hebt bijgewerkt, veroorzaakt de toepassing deserialisatie-excepties bij het lezen vanuit de gedistribueerde cache. Gebruikers moeten zich opnieuw aanmelden en u ziet uitzonderingen zoals:

System.Text.Json.JsonException:
  The JSON value could not be converted to the expected type.

Of:

Microsoft.Identity.Client.MsalClientException:
  Error code: json_parse_failed

Oorzaak

De serialisatie-indeling van de tokencache is gewijzigd tussen bibliotheekversies. Tokens die door de vorige versie in de cache zijn opgeslagen, kunnen niet worden gedeserialiseerd door de nieuwe versie. Dit probleem treedt meestal op tijdens de primaire versie-upgrades van MSAL.NET of Microsoft. Identity.Web.

Solution

Optie A: De cache wissen

De eenvoudigste oplossing is om alle vermeldingen in de gedistribueerde cache te wissen. Gebruikers worden eenmaal opnieuw geverifieerd en de volgende tokens worden geschreven in de nieuwe indeling.

De Redis-cache leegmaken:

redis-cli FLUSHDB

Of wis de SQL Server gedistribueerde cachetabel:

DELETE FROM [dbo].[TokenCache];

Opmerking

Door de cache te wissen, moeten alle actieve gebruikers zich opnieuw aanmelden. Plan deze bewerking tijdens een onderhoudsvenster als uw toepassing een groot gebruikersbestand bedient.

Optie B: Fouten met deserialisatie correct afhandelen

Stel de cache-adapter zo in dat deserialisatiefouten worden beschouwd als cache-misses in plaats van fatale fouten.

services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
    options.OnL2CacheFailure = (ex) =>
    {
        if (ex is JsonException or MsalClientException)
        {
            logger.LogWarning(ex, "Cache deserialization failed. " +
                "Treating as cache miss.");
            return true;
        }
        return false; // Propagate unexpected errors.
    };
});

Met deze methode worden betrokken cachevermeldingen automatisch vervangen als gebruikers opnieuw verifiëren en is er geen handmatige cache leegmaken vereist.

Versleutelingssleutel komt niet overeen tussen servers

Symptoom

Deserialisatiefouten treden op in implementaties met meerdere exemplaren, ook al werkt de gedistribueerde cache. Tokens die door één serverexemplaren in de cache worden opgeslagen, kunnen niet worden gelezen door een ander exemplaar. U ziet json_parse_failed of IDW10802 fouten in de logboeken.

Oorzaak

Wanneer cacheversleuteling is ingeschakeld (options.Encrypt = true), Microsoft. Identity.Web maakt gebruik van ASP.NET Core Data Protection om cachevermeldingen te versleutelen. Standaard genereert elk serverexemplaar zijn eigen gegevensbeveiligingssleutels, zodat het ene exemplaar geen vermeldingen kan decrypten die zijn geschreven door een ander.

Solution

Configureer ASP.NET Core Data Protection om versleutelingssleutels te delen in alle serverexemplaren.

Option A: Azure Blob Storage + Azure Key Vault (aanbevolen voor Azure implementaties)

using Microsoft.AspNetCore.DataProtection;
using Azure.Identity;

builder.Services.AddDataProtection()
    .PersistKeysToAzureBlobStorage(
        new Uri("https://yourstorageaccount.blob.core.windows.net/dataprotection/keys.xml"),
        new DefaultAzureCredential())
    .ProtectKeysWithAzureKeyVault(
        new Uri("https://yourkeyvault.vault.azure.net/keys/dataprotection-key"),
        new DefaultAzureCredential());

builder.Services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
    options.Encrypt = true;
});

Met deze configuratie wordt de sleutelring voor gegevensbescherming opgeslagen in Azure Blob Storage en worden de sleutels in rust beschermd met Azure Key Vault. Alle toepassingsexemplaren die toegang hebben tot dezelfde blob en sleutel, kunnen elkaars cachevermeldingen versleutelen en ontsleutelen.

Optie B: Gedeeld bestandssysteem met certificaatbeveiliging

builder.Services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\keys"))
    .ProtectKeysWithCertificate(certificate);

Aanbeveling

Wanneer u het Data Protection-certificaat roteert, gebruikt UnprotectKeysWithAnyCertificate u deze om zowel de huidige als de vorige certificaten op te nemen. Hierdoor kunnen sleutels die tijdens het rotatievenster met het oude certificaat zijn beveiligd, worden ontsleuteld.

Geheugengroei met in-memory cache

Symptoom

Het verbruik van toepassingsgeheugen neemt geleidelijk toe. Als de toepassing wordt uitgevoerd in een container of App Service-plan met een vaste geheugenlimiet, wordt deze uiteindelijk opnieuw opgestart of gegooid OutOfMemoryException. Bewaking toont dat de beheerde heap groeit zonder reclamatie door garbagecollection.

Oorzaak

Het gebruik zonder AddInMemoryTokenCaches() groottelimieten zorgt voor niet-gebonden cachegroei. Deze situatie is vooral problematisch in toepassingen die veel gebruikers bedienen, omdat de tokenvermelding van elke gebruiker voor onbepaalde tijd geheugen verbruikt.

Standaard dwingt MemoryCache geen maximale grootte af en worden vermeldingen niet verwijderd, tenzij een vervalbeleid is ingesteld.

Solution

Optie A: Een groottelimiet en een verschuivende vervaldatum instellen

Configureer de cache in het geheugen met verloopbeleid:

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(Configuration)
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddInMemoryTokenCaches();

services.Configure<MsalMemoryTokenCacheOptions>(options =>
{
    options.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(12);
    options.SlidingExpiration = TimeSpan.FromHours(2);
});

Met deze instellingen verlopen vermeldingen na 12 uur, ongeacht de toegang en vermeldingen die gedurende 2 uur inactief zijn, eerder verwijderd.

Optie B: Overschakelen naar een gedistribueerde cache

Voor toepassingen met veel gelijktijdige gebruikers wordt een cache in het geheugen niet geschaald. Overschakelen naar een gedistribueerde cache, zoals Redis:

services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = Configuration.GetConnectionString("Redis");
});

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(Configuration)
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddDistributedTokenCaches();

Een gedistribueerde cache vermindert de geheugenbelasting van het toepassingsproces, bewaart de tokens bij herstarten en ondersteunt implementaties met meerdere instanties.

Optie C: De hybride L1/L2-architectuur gebruiken

Microsoft. Identity.Web ondersteunt een hybride benadering die een snelle L1-cache in het geheugen combineert met een permanente gedistribueerde L2-cache. Stel de hybride L1/L2-cache in:

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(Configuration)
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddDistributedTokenCaches();

services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
    options.L1CacheOptions = new MsalMemoryTokenCacheOptions
    {
        AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5),
        SlidingExpiration = TimeSpan.FromMinutes(2)
    };
});

Met L1/L2-caching worden veelgebruikte tokens geleverd vanuit het geheugen (L1) met latentie van minder dan milliseconden. De L2-cache biedt persistentie en consistentie tussen exemplaren. De L1-cache maakt gebruik van korte vervaldatums om de geheugengroei te beperken.

Symptoom

Gebruikers worden herhaaldelijk gevraagd om meervoudige verificatie (MFA) of toestemming, ook al hebben ze deze stappen onlangs voltooid. De toepassing kan bestaande tokens niet vinden in de cache.

Oorzaak

Dit probleem treedt op wanneer het opzoeken van de tokencache niet overeenkomt met een vermelding in de cache voor het huidige gebruikersaccount. Veelvoorkomende oorzaken zijn onder andere:

  • De cachesleutel verschilt van de sleutel die wordt gebruikt wanneer het token is opgeslagen. Deze situatie kan optreden als de context van de HomeAccountId of de context van de tenant verandert.
  • De toepassing voert meerdere exemplaren achter een load balancer uit met cacheopslag in het geheugen en vraagt om een route naar een exemplaar dat geen token van de gebruiker heeft.
  • De aangevraagde claims of scopes zijn gewijzigd, waardoor het token in de cache niet voldoet aan de nieuwe vereiste.
  • Sessie-affiniteit is niet ingeschakeld, waardoor gebruikers worden doorgestuurd naar verschillende instanties die hun gecachte tokens missen.

Diagnostische stappen

Volg deze stappen om te bepalen waarom tokens niet worden gevonden in de cache:

  1. Controleer het cachetype. Als u in een implementatie met meerdere exemplaren gebruikt AddInMemoryTokenCaches() , zijn tokens die in de cache op het ene exemplaar zijn opgeslagen, niet beschikbaar op een ander exemplaar. Schakel over naar een gedistribueerde cache.
  2. Controleer de account-id. Schakel logboekregistratie op debug-niveau in en zoek naar de HomeAccountId. Controleer of de id consistent is voor alle aanvragen.
  3. Inspecteer de bereiken. Controleer of de bereiken die zijn aangevraagd door GetAccessTokenForUserAsync overeenkomen met de bereiken waarvoor oorspronkelijk toestemming is gegeven. Een bereik komt niet overeen, waardoor MSAL een nieuw token aanvraagt.
  4. Controleer het beleid voor voorwaardelijke toegang. Een Microsoft Entra ID beleid voor voorwaardelijke toegang waarvoor stapsgewijze verificatie is vereist voor specifieke resources, zorgt ervoor dat extra prompts niet gerelateerd zijn aan caching.

Solution

Stap 1: Overschakelen naar gedistribueerde caching

Als uw toepassing meerdere exemplaren uitvoert, gebruikt u een gedistribueerde cache om tokens te delen tussen exemplaren:

services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = Configuration.GetConnectionString("Redis");
});

services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(Configuration)
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddDistributedTokenCaches();

Stap 2: Consistente scopen controleren

Zorg ervoor dat de scopes die u aanvraagt bij het verkrijgen van tokens overeenkomen met de scopes die tijdens de authenticatie zijn geconfigureerd.

// In authentication setup — initial scopes.
.EnableTokenAcquisitionToCallDownstreamApi(new[] { "User.Read", "Mail.Read" })

// When acquiring a token — use the same scopes.
var token = await tokenAcquisition.GetAccessTokenForUserAsync(
    new[] { "User.Read", "Mail.Read" });

Stap 3: Sessieaffiniteit inschakelen (tijdelijke tijdelijke oplossing)

Als u niet meteen kunt overschakelen naar een gedistribueerde cache, schakelt u sessieaffiniteit (plaksessies) in op uw load balancer. Sessieaffiniteit routeert de aanvragen van een gebruiker naar dezelfde instantie. Deze aanpak is een tijdelijke tijdelijke oplossing met schaalbaarheidsbeperkingen.

Prestatieproblemen met cache

Symptoom

Het ophalen van tokens is traag en downstream-API-aanroepen hebben een verhoogde latentie. Bewaking toont hoge gemiddelde reactietijden voor aanvragen voor tokenaanwerving. De latentie is niet afkomstig van de id-provider. Tokens worden geleverd vanuit de cache.

Oorzaak

Prestatieproblemen met cache zijn meestal het gevolg van:

  • Hoge L2-cachelatentie. De gedistribueerde cache is zwaar belast, geografisch ver van de toepassing, of gebruikt een onderbemeten servicelaag.
  • Grote tokencachevermeldingen. Toepassingen die tokens opslaan voor veel resources per gebruiker, kunnen grote geserialiseerde cachevermeldingen produceren die langzaam worden gelezen en geschreven.
  • Geen L1 cache. Elke tokenovername gaat naar de gedistribueerde cache via het netwerk, zelfs voor tokens die vaak worden gebruikt.

Solution

Stap 1: De L1-cache in het geheugen inschakelen

In de L1-cache worden vaak gebruikte tokens opgeslagen in procesgeheugen, waardoor netwerkrondes naar L2 worden voorkomen:

services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
    options.L1CacheOptions = new MsalMemoryTokenCacheOptions
    {
        AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5),
        SlidingExpiration = TimeSpan.FromMinutes(2)
    };
});

Met deze configuratie hebben tokens van L1 een latentie van submilliseconden. Tokens die niet in L1 zijn opgenomen, vallen terug op de gedistribueerde L2-cache.

Stap 2: De gedistribueerde cachelaag optimaliseren

Als de latentie van de L2-cache hoog is, kunt u de volgende acties overwegen:

  • Schaal het Redis-exemplaar omhoog. Ga naar een hogere laag (bijvoorbeeld van Basic naar Standard of Premium in Azure Cache voor Redis) om meer doorvoer en lagere latentie te krijgen.
  • Inschakelen van geo-replicatie. Als uw toepassing gebruikers in meerdere regio's bedient, gebruikt u Azure Cache voor Redis geo-replicatie, zodat de cache dicht bij de berekening van elke regio ligt.
  • Controleer de netwerkconfiguratie. Gebruik Private Link of VNet-integratie om netwerkhops tussen de toepassing en de cache te verminderen.

Stap 3: Grootte van geserialiseerd token verkleinen

Als tokencachevermeldingen groot zijn, controleert u of de toepassing tokens aanvraagt voor meer resources dan nodig is. Elke unieke combinatie van resource en bereik draagt bij aan de cache-ingangsgrootte. Voeg waar mogelijk API-aanroepen samen om het aantal afzonderlijke toegangstokens per gebruiker in de cache te verminderen.

Verwijdering van Redis-cache

Symptoom

Gebruikers worden af en toe gevraagd om opnieuw te authentiseren zonder dat er een patroon kan worden ontdekt met betrekking tot de tokenverloop. Redis-bewaking toont evicted_keys het verhogen en used_memory naderen van de maxmemory limiet.

Oorzaak

Wanneer Redis de maxmemory limiet bereikt, worden sleutels verwijderd op basis van de geconfigureerde maxmemory-policy. Met het standaardbeleid (volatile-lru) worden de minst recent gebruikte sleutels verwijderd die een vervaldatum hebben. Als het Redis-exemplaar wordt gedeeld met andere toepassingsgegevens, concurreren tokencache-items voor ruimte en kunnen ze voortijdig worden verwijderd.

Solution

Stap 1: Het verwijderingsbeleid controleren

Controleer het huidige verwijderingsbeleid:

redis-cli CONFIG GET maxmemory-policy

Voor tokencaches is volatile-lru (de standaardinstelling) geschikt omdat tokencachevermeldingen verlopen. Als andere gegevens zonder verlooptijd echter geheugen verbruiken, worden tokenvermeldingen eerst verwijderd.

Stap 2: Een toegewezen Redis-exemplaar gebruiken

Isoleer de tokencache van andere toepassingsgegevens met behulp van een toegewezen Redis-exemplaar:

{
  "ConnectionStrings": {
    "RedisTokenCache": "token-cache-redis.redis.cache.windows.net:6380,password=...,ssl=True,abortConnect=False",
    "RedisAppData": "app-data-redis.redis.cache.windows.net:6380,password=...,ssl=True,abortConnect=False"
  }
}
// Register the token cache Redis instance specifically for distributed caching.
services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = Configuration.GetConnectionString("RedisTokenCache");
});

Stap 3: de Geheugenlimiet van Redis verhogen

Als een dedicated instance niet haalbaar is, verhoogt u de maxmemory parameter. In Azure Cache voor Redis kunt u omhoog schalen naar een hogere laag of de cachegrootte vergroten.

Stap 4: De juiste verlooptijd van cachevermelding instellen

Stel redelijke vervaldatums in, zodat verlopen vermeldingen worden verwijderd voordat het geheugen opraakt:

services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
    options.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(12);
    options.SlidingExpiration = TimeSpan.FromHours(2);
});

Groei van gedistribueerde SQL-cachetabellen

Symptoom

De tabel met gedistribueerde SQL-cache groeit voortdurend en verbruikt schijfruimte. Databasequery's voor de cachetabel worden na verloop van tijd traag weergegeven en u ziet mogelijk waarschuwingen over tabelgrootte of opslaglimieten.

Oorzaak

De SQL Server gedistribueerde cache (Microsoft.Extensions.Caching.SqlServer) verwijdert niet automatisch verlopen vermeldingen. Verlopen vermeldingen blijven behouden totdat ze expliciet zijn opgeschoond, wat leidt tot niet-gebonden tabelgroei, verminderde queryprestaties en opslagverbruik.

Solution

Stap 1: Een terugkerende opschoontaak instellen

Maak een SQL Server Agent taak of geplande taak om regelmatig verlopen items te verwijderen:

-- Delete expired entries from the SQL distributed cache table.
-- Schedule this query to run every 30 minutes.
DELETE FROM [dbo].[TokenCache]
WHERE ExpiresAtTime < GETUTCDATE();

Aanbeveling

Gebruik in Azure SQL Database, waar SQL Server Agent niet beschikbaar is, Azure Automation, Azure Functions met een timertrigger of Elastische taken om de opschoonbewerking te plannen.

Stap 2: Een index toevoegen voor efficiënt opschonen

Als de cachetabel nog geen index voor de verloopkolom bevat, voegt u er een toe om de verwijderbewerking te versnellen:

CREATE NONCLUSTERED INDEX IX_TokenCache_ExpiresAtTime
ON [dbo].[TokenCache] (ExpiresAtTime);

Stap 3: Tabelgrootte bewaken

Voeg bewaking toe om het aantal rijen en de tabelgrootte in de loop van de tijd bij te houden:

SELECT
    COUNT(*) AS TotalEntries,
    COUNT(CASE WHEN ExpiresAtTime < GETUTCDATE() THEN 1 END) AS ExpiredEntries,
    COUNT(CASE WHEN ExpiresAtTime >= GETUTCDATE() THEN 1 END) AS ActiveEntries
FROM [dbo].[TokenCache];

Stap 4: Overweeg over te schakelen naar Redis

Als het opschonen van SQL-cache lastig is, schakelt u over naar Redis, waarmee de vervaldatum automatisch wordt verwerkt via het ingebouwde TTL-mechanisme:

// Replace SQL distributed cache with Redis.
services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = Configuration.GetConnectionString("Redis");
});

Algemene tips voor probleemoplossing

Gebruik deze tips wanneer uw probleem niet overeenkomt met een specifiek scenario in dit artikel.

Controleren of de cache wordt gebruikt

Voeg tijdelijke logboekregistratie toe om te bevestigen dat tokens worden gelezen en naar de cache worden geschreven:

services.Configure<MsalDistributedTokenCacheAdapterOptions>(options =>
{
    options.Encrypt = false; // Disable encryption temporarily for debugging only.
    options.OnL2CacheFailure = (ex) =>
    {
        logger.LogError(ex, "L2 cache operation failed.");
        return true;
    };
});

Controleren op meerdere cacheregistraties

Als er meerdere aanroepen naar AddInMemoryTokenCaches() of AddDistributedTokenCaches() bestaan in uw opstartcode, wint de laatste registratie. Controleer of er slechts één cachetype is geregistreerd.

De levensduur van het token controleren

Toegangstokens hebben een eindige levensduur (meestal 60-90 minuten). Als gebruikers na deze periode opnieuw moeten aanmelden, wordt dit gedrag verwacht in plaats van dat er sprake is van een cacheprobleem. Refresh tokens verkrijgen stilletjes nieuwe toegangstokens en worden opgeslagen in de cache. Als het refresh-token ontbreekt of is verlopen, moet de gebruiker opnieuw authentiseren.

Testen met een schone cache

Bij het diagnosticeren van problemen, wis de cache om beschadigde of verouderde vermeldingen uit te sluiten.

  • Cache in het geheugen: Start de toepassing opnieuw op.
  • nl-NL: Redis: Voer FLUSHDB uit op de cachedatabase.
  • SQL Server: Alle rijen uit de cachetabel verwijderen.

Tokencache leeg nadat de toepassing opnieuw is opgestart

Symptoom

Gebruikers moeten na elke herstart of herimplementatie opnieuw verifiëren. De gedistribueerde cache lijkt leeg of tokens worden niet opgeslagen.

Oorzaak

Dit probleem treedt meestal op wanneer u een in-memory cache (AddInMemoryTokenCaches()) of de niet-permanente gedistribueerde geheugencache (AddDistributedMemoryCache()) in productie gebruikt. Geen van beide opties behoudt tokens na het opnieuw opstarten van de toepassing.

AddDistributedMemoryCache() registreert een IDistributedCache implementatie waarin gegevens in het geheugen worden opgeslagen. Ondanks de 'gedistribueerde' naam worden gegevens niet extern bewaard en is alleen bedoeld voor ontwikkeling en testen.

Solution

Overschakelen naar een permanente gedistribueerde cache:

// Register a persistent cache (Redis example).
builder.Services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = builder.Configuration.GetConnectionString("Redis");
    options.InstanceName = "MyApp_";
});

// Use distributed token caches instead of in-memory.
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(builder.Configuration)
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddDistributedTokenCaches();

Waarschuwing

Verwar AddDistributedMemoryCache() niet met een permanente gedistribueerde cache. Gebruik AddStackExchangeRedisCache() (Redis), AddDistributedSqlServerCache() (SQL Server) of een andere permanente IDistributedCache-implementatie voor productieworkloads.