Resuelva los problemas de caché de tokens en Microsoft. Identity.Web

Este artículo le ayuda a diagnosticar y resolver problemas de caché de tokens en Microsoft. Identity.Web. Los problemas de caché de tokens pueden provocar errores de autenticación, un rendimiento degradado o mensajes de inicio de sesión inesperados. Para obtener información general sobre cómo funciona el almacenamiento en caché de tokens en Microsoft. Identity.Web, consulte Token cache overview.

Prerrequisitos

Antes de solucionar problemas, confirme lo siguiente:

  • Usa una versión compatible de Microsoft. Identity.Web.
  • La aplicación tiene el almacenamiento en caché de tokens configurado en Program.cs o Startup.cs.
  • Tiene acceso a los registros de aplicaciones y, si procede, a la infraestructura de caché distribuida.

Habilitación del registro y diagnóstico de la caché de tokens

Habilite el registro detallado como primer paso de diagnóstico. Microsoft. Identity.Web usa la infraestructura de registro de ASP.NET Core y emite eventos a través de la Biblioteca de autenticación de Microsoft (MSAL).

Habilita el registro de MSAL

Establezca el nivel de registro en Debug para las bibliotecas de identidad en appsettings.json:

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

Suscribirse a eventos de caché de MSAL

Suscríbase a eventos de notificación del caché de tokens de MSAL para realizar un seguimiento de los aciertos, fallos y seguimiento de la actividad de serialización del caché.

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;
    };
});

Supervisión de métricas de caché

Para la supervisión de producción, realice un seguimiento de estas métricas clave:

  • Tasa de aciertos de caché : una tasa de aciertos baja indica que los tokens no se recuperan de la memoria caché.
  • Latencia de caché L2 : latencia alta sugiere un problema de rendimiento o conectividad de caché distribuida.
  • Errores de serialización de caché — los errores durante la lectura o escritura indican una corrupción o un desajuste de versiones.
  • Consumo de memoria — el crecimiento sostenido puede indicar que faltan políticas de eliminación.

Errores de conexión de caché distribuida (L2)

Síntoma

Los registros de aplicación muestran errores de tiempo de espera de conexión o errores de autenticación intermitentes. Los usuarios experimentan retrasos en el inicio de sesión y pueden ver excepciones como:

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

O para la caché distribuida de SQL Server:

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

Causa

El almacén de respaldo de caché distribuida (Redis o SQL Server) no es accesible. Las causas más comunes son:

  • "Cadena de conexión incorrecta o credenciales de acceso expiradas."
  • Reglas de firewall de red que bloquean la conexión desde el host de la aplicación.
  • El servicio de caché está inactivo o está en mantenimiento.
  • Error de coincidencia de configuración de SSL/TLS entre el cliente y el servidor de caché.

Pasos de diagnósticos

Siga estos pasos para identificar el error de conexión:

  1. Compruebe la conectividad. Desde el host de la aplicación, pruebe la conexión a Redis o SQL Server mediante Test-NetConnection (PowerShell) o redis-cli.
  2. Compruebe la cadena de conexión. Confirme que el cadena de conexión coincide con el nombre de host, el puerto y las credenciales del servidor de caché.
  3. Revise las reglas de firewall. En Azure, compruebe que app service o la red virtual puedan acceder al recurso de caché.
  4. Comprobar el estado del servicio. En el portal de Azure, revise el estado y las métricas de la instancia de Azure Cache for Redis o SQL Database.

Solución

Paso 1: Corrija la cadena de conexión

Compruebe la cadena de conexión en su appsettings.json:

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

Importante

Establezca abortConnect=False en el cadena de conexión de Redis. Esta configuración permite que la aplicación se vuelva a conectar automáticamente después de fallos de conexión transitorios en lugar de arrojar un error inmediatamente.

Paso 2: Configuración del reintento y la resistencia

Configura la OnL2CacheFailure devolución de llamada para que tu aplicación se degrade de manera elegante cuando la caché distribuida no esté disponible temporalmente:

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);
});

Paso 3: Apertura de reglas de firewall

Si la aplicación se ejecuta en Azure App Service y la caché está en una red virtual, agregue las direcciones IP de salida de App Service a la lista de permitidos del firewall de caché.

Errores de deserialización de caché

Síntoma

Después de actualizar Microsoft. Identity.Web o MSAL.NET, la aplicación produce excepciones de deserialización al leer desde la caché distribuida. Los usuarios deben iniciar sesión de nuevo y verá excepciones como:

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

O:

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

Causa

El formato de serialización de la caché de tokens cambió entre versiones de la biblioteca. Los tokens almacenados en caché por la versión anterior no se pueden deserializar mediante la nueva versión. Este problema se produce con más frecuencia durante las actualizaciones de versiones principales de MSAL.NET o Microsoft. Identity.Web.

Solución

Opción A: Borrar la memoria caché

La corrección más sencilla es borrar todas las entradas de la caché distribuida. Los usuarios vuelven a autenticarse una vez y los tokens posteriores se escriben en el nuevo formato.

Vaciar la caché de Redis

redis-cli FLUSHDB

O borre la tabla de caché distribuida de SQL Server:

DELETE FROM [dbo].[TokenCache];

Nota:

Borrar la caché hace que todos los usuarios activos vuelvan a autenticarse. Planee esta operación durante una ventana de mantenimiento si la aplicación atiende una base de usuarios grande.

Opción B: Manejar los errores de deserialización de manera adecuada

Configure el adaptador de caché para tratar los errores de deserialización como errores de caché en lugar de errores irrecuperables:

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.
    };
});

Con este enfoque, las entradas de caché afectadas se reemplazan automáticamente a medida que los usuarios vuelven a autenticarse y no se requiere ningún vaciado de caché manual.

Error de coincidencia de clave de cifrado entre servidores

Síntoma

Los errores de deserialización se producen en implementaciones de instancias múltiples aunque la caché distribuida funcione. Otro no puede leer los tokens almacenados en caché por una instancia de servidor. Usted ve errores json_parse_failed o IDW10802 en los registros.

Causa

Cuando se habilita el cifrado de caché (options.Encrypt = true), Microsoft. Identity.Web usa ASP.NET Core Data Protection para cifrar las entradas de caché. De forma predeterminada, cada instancia de servidor genera sus propias claves de protección de datos, por lo que una instancia no puede descifrar entradas escritas por otra.

Solución

Configure la Protección de datos de ASP.NET Core para compartir claves de cifrado en todas las instancias del servidor.

Option A: Azure Blob Storage + Azure Key Vault (recomendado para implementaciones de Azure)

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;
});

Esta configuración almacena el anillo de claves de protección de datos en Azure Blob Storage y protege las claves en reposo con Azure Key Vault. Todas las instancias de aplicación que tienen acceso al mismo blob y clave pueden cifrar y descifrar las entradas de caché de los demás.

Opción B: Sistema de archivos compartido con protección de certificados

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

Sugerencia

Al rotar el certificado de protección de datos, use UnprotectKeysWithAnyCertificate para incluir los certificados actuales y anteriores. Esto permite descifrar las claves protegidas con el certificado antiguo durante la ventana de rotación.

Crecimiento de memoria con caché en memoria

Síntoma

El consumo de memoria de la aplicación aumenta constantemente con el tiempo. Si la aplicación se ejecuta en un contenedor o un plan de App Service con un límite de memoria fijo, finalmente se reinicia o genera una excepción OutOfMemoryException. La supervisión muestra el crecimiento del montón administrado sin la reclamación por la recolección de basura.

Causa

El uso AddInMemoryTokenCaches() sin límites de tamaño provoca un crecimiento ilimitado de la memoria caché. Esta situación es especialmente problemática en las aplicaciones que sirven a muchos usuarios, ya que la entrada de token de cada usuario consume memoria indefinidamente.

De forma predeterminada, MemoryCache no aplica un tamaño máximo y no expulsa las entradas a menos que se establezca una directiva de expiración.

Solución

Opción A: Establecer un límite de tamaño y una expiración deslizante

Configure la caché en memoria con directivas de expiración:

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

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

Con esta configuración, las entradas expiran después de 12 horas independientemente del acceso y las entradas inactivas durante 2 horas se expulsan anteriormente.

Opción B: Cambiar a una caché distribuida

En el caso de aplicaciones con muchos usuarios simultáneos, una memoria caché no escala. Cambie a una caché distribuida como Redis:

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

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

Una caché distribuida descarga la memoria del proceso de aplicación, conserva los tokens entre reinicios y admite implementaciones de varias instancias.

Opción C: Uso de la arquitectura híbrida L1/L2

Microsoft. Identity.Web admite un enfoque híbrido que combina una caché L1 en memoria rápida con una caché L2 distribuida persistente. Configurar la caché híbrida L1/L2:

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

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

Con el almacenamiento en caché L1/L2, los tokens a los que se accede con frecuencia se sirven desde la memoria (L1) con latencia de submilisegundos. La caché L2 proporciona persistencia y coherencia entre instancias. La memoria caché L1 usa expiraciones cortas para limitar el crecimiento de la memoria.

Síntoma

Los usuarios se solicitan repetidamente la autenticación multifactor (MFA) o el consentimiento aunque hayan completado estos pasos recientemente. La aplicación no puede encontrar tokens existentes en la memoria caché.

Causa

Este problema se produce cuando la búsqueda de caché de tokens no coincide con una entrada almacenada en caché en la cuenta de usuario actual. Las causas más comunes son:

  • La clave de caché difiere de la usada cuando se almacenó el token. Esta situación puede producirse si cambia el contexto del HomeAccountId o del inquilino.
  • La aplicación ejecuta múltiples instancias detrás de un balanceador de carga con caché en memoria, y las solicitudes se enrutan a una instancia que no tiene el token del usuario.
  • Las notificaciones o ámbitos solicitados han cambiado, por lo que el token almacenado en caché no satisface el nuevo requisito.
  • La afinidad de sesión no está habilitada, por lo que los usuarios son direccionados a diferentes instancias sin sus tokens en caché.

Pasos de diagnósticos

Siga estos pasos para identificar por qué no se encuentran los tokens en la memoria caché:

  1. Compruebe el tipo de caché. Si usa AddInMemoryTokenCaches() en una implementación de varias instancias, los tokens almacenados en caché en una instancia no están disponibles en otra. Cambie a una caché distribuida.
  2. Compruebe el identificador de la cuenta. Habilite el registro de depuración de nivel y busque el HomeAccountId. Confirme que el identificador es coherente entre las solicitudes.
  3. Inspeccione los alcances. Confirme que los ámbitos solicitados por GetAccessTokenForUserAsync coincidan con los ámbitos con los que se consiente originalmente. Una falta de coincidencia de ámbito hace que MSAL solicite un nuevo token.
  4. Revise las directivas de acceso condicional. Una Microsoft Entra ID directiva de acceso condicional que requiere autenticación paso a paso para recursos específicos provoca solicitudes adicionales no relacionadas con el almacenamiento en caché.

Solución

Paso 1: Cambiar al almacenamiento en caché distribuido

Si la aplicación ejecuta varias instancias, use una caché distribuida para compartir tokens entre instancias:

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

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

Paso 2: Comprobación de ámbitos coherentes

Asegúrese de que los ámbitos que solicite al adquirir tokens coincidan con los ámbitos configurados durante la autenticación:

// 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" });

Paso 3: Habilitar la afinidad de sesión (solución alternativa temporal)

Si no puede cambiar a una caché distribuida inmediatamente, habilite la afinidad de sesión (sesiones permanentes) en el equilibrador de carga. La afinidad de sesión enruta las solicitudes de un usuario a la misma instancia. Este enfoque es una solución temporal con limitaciones de escalabilidad.

Problemas de rendimiento de caché

Síntoma

La recuperación de tokens es lenta y las llamadas API descendentes han aumentado la latencia. La supervisión muestra tiempos de respuesta medios elevados para las solicitudes de adquisición de tokens. La latencia no procede del proveedor de identidades: los tokens se sirven desde la memoria caché.

Causa

Los problemas de rendimiento de la caché suelen deberse a:

  • Latencia alta de caché L2. La caché distribuida está bajo carga pesada, geográficamente distante de la aplicación o mediante un nivel de servicio infradimensionado.
  • Entradas de caché de tokens grandes. Las aplicaciones que almacenan en caché tokens para muchos recursos por usuario pueden generar entradas de caché grandes y serializadas que son lentas de leer y escribir.
  • No hay caché de nivel 1. Cada adquisición de tokens va a la caché distribuida a través de la red, incluso para los tokens que se usan con frecuencia.

Solución

Paso 1: Habilitar la caché en memoria L1

La caché L1 almacena tokens a los que se accede con frecuencia en la memoria del proceso, evitando los recorridos de ida y vuelta de red a L2:

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

Con esta configuración, los tokens servidos desde L1 tienen latencia de submilisegundos. Los tokens que no están en L1 recurren a la caché distribuida en L2.

Paso 2: Optimizar el nivel de caché distribuida

Si la latencia de caché L2 es alta, tenga en cuenta las siguientes acciones:

  • Escale verticalmente la instancia de Redis. Vaya a un nivel superior (por ejemplo, de Básico a Estándar o Premium en Azure Cache for Redis) para obtener más rendimiento y menor latencia.
  • Habilite la replicación geográfica. Si su aplicación atiende a usuarios en varias regiones, use Azure Cache for Redis con replicación geográfica para que la memoria caché esté cerca de la capacidad de cómputo de cada región.
  • Revise la configuración de red. Use Private Link o integración de red virtual para reducir los saltos de red entre la aplicación y la memoria caché.

Paso 3: Reducir el tamaño del token serializado

Si las entradas de caché de tokens son grandes, revise si la aplicación solicita tokens para más recursos de los necesarios. Cada combinación única de recursos y ámbitos agrega al tamaño de la entrada en caché. Consolide las llamadas API siempre que sea posible para reducir el número de tokens de acceso distintos almacenados en caché por usuario.

Expulsión de caché de Redis

Síntoma

A los usuarios se les pide de forma intermitente que vuelvan a autenticarse sin ningún patrón basado en la expiración del token. La supervisión de Redis muestra un aumento en evicted_keys y una aproximación a used_memory hacia el límite de maxmemory.

Causa

Cuando Redis alcanza su límite maxmemory, expulsa las claves según la configuración de maxmemory-policy. La directiva predeterminada (volatile-lru) expulsa las claves usadas menos recientemente que tienen una expiración. Si la instancia de Redis se comparte con otros datos de la aplicación, las entradas de caché de tokens compiten por el espacio y se pueden expulsar prematuramente.

Solución

Paso 1: Comprobación de la directiva de expulsión

Compruebe la directiva de expulsión actual:

redis-cli CONFIG GET maxmemory-policy

En el caso de las memorias caché de tokens, volatile-lru (el valor predeterminado) es adecuado porque las entradas de caché de tokens tienen expiraciones. Sin embargo, si otros datos sin expiraciones consumen memoria, primero se expulsan las entradas de token.

Paso 2: Uso de una instancia dedicada de Redis

Aísle la caché de tokens de otros datos de la aplicación mediante una instancia de Redis dedicada:

{
  "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");
});

Paso 3: Aumento del límite de memoria de Redis

Si una instancia dedicada no es factible, aumente la maxmemory configuración. En Azure Cache for Redis, escale verticalmente a un nivel superior o aumente el tamaño de la caché.

Paso 4: Establecer las expiraciones de entrada de caché adecuadas

Establezca expiraciones razonables para que las entradas obsoletas se quiten antes de que se agote la memoria:

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

Crecimiento de la tabla de caché distribuida de SQL

Síntoma

La tabla de caché distribuida de SQL crece continuamente y consume espacio en disco. Las consultas de base de datos en la tabla de caché se ralentizan con el tiempo y es posible que vea advertencias sobre el tamaño de la tabla o los límites de almacenamiento.

Causa

La caché distribuida SQL Server (Microsoft.Extensions.Caching.SqlServer) no quita automáticamente las entradas expiradas. Las entradas expiradas permanecen hasta que se purgan explícitamente, lo que provoca el crecimiento ilimitado de tablas, el rendimiento degradado de las consultas y el consumo de almacenamiento.

Solución

Paso 1: Configurar un trabajo de limpieza periódico

Cree un trabajo de Agente SQL Server o una tarea programada para quitar periódicamente entradas expiradas:

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

Sugerencia

En Azure SQL Database, donde Agente SQL Server no está disponible, use Azure Automation, Azure Functions con un desencadenador de temporizador o trabajos elásticos para programar la limpieza.

Paso 2: Agregar un índice para una limpieza eficaz

Si la tabla de caché aún no tiene un índice en la columna de expiración, agregue uno para acelerar la operación de eliminación:

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

Paso 3: Supervisión del tamaño de la tabla

Agregue supervisión para realizar un seguimiento del número de filas y el tamaño de la tabla a lo largo del tiempo:

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];

Paso 4: Considere la posibilidad de cambiar a Redis

Si la administración de la limpieza de la caché de SQL es pesada, cambie a Redis, que controla la expiración automáticamente a través de su mecanismo de TTL integrado:

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

Sugerencias para solución de problemas generales

Use estas sugerencias cuando el problema no coincida con un escenario específico de este artículo.

Comprobación de que se está usando la memoria caché

Agregue el registro temporal para confirmar que los tokens se leen y escriben en la memoria caché:

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;
    };
});

Comprobación de varios registros de caché

** Si en el código de inicio existen varias llamadas a AddInMemoryTokenCaches() o AddDistributedTokenCaches(), la última inscripción tiene prioridad. Compruebe que solo hay un tipo de caché registrado.

Revisión de la duración del token

Los tokens de acceso tienen una duración finita (normalmente de 60 a 90 minutos). Si los usuarios notifican la nueva autenticación después de este período, se espera el comportamiento en lugar de un problema de caché. Los tokens de actualización obtienen nuevos tokens de acceso de forma silenciosa y se almacenan en la memoria caché. Si falta el token de actualización o ha expirado, el usuario debe volver a autenticarse.

Prueba con una caché limpia

Al diagnosticar problemas, borre la memoria caché para descartar entradas dañadas o obsoletas:

  • Caché en memoria: Reinicie la aplicación.
  • Redis: Ejecute FLUSHDB en la base de datos de caché.
  • SQL Server: Eliminar todas las filas de la tabla de caché.

Caché de tokens vacía después del reinicio de la aplicación

Síntoma

Los usuarios deben volver a autenticarse después de reiniciar o volver a implementar la aplicación. La caché distribuida aparece vacía o los tokens no se conservan.

Causa

Este problema suele producirse cuando se usa una caché en memoria (AddInMemoryTokenCaches()) o la caché de memoria distribuida no persistente (AddDistributedMemoryCache()) en producción. Ninguna opción conserva los tokens en los reinicios de la aplicación.

AddDistributedMemoryCache() registra una IDistributedCache implementación que almacena los datos en la memoria. A pesar del nombre "distribuido", no conserva los datos externamente y está pensado solo para desarrollo y pruebas.

Solución

Cambie a una caché distribuida persistente:

// 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();

Advertencia

No confunda AddDistributedMemoryCache() con una caché distribuida persistente. Use AddStackExchangeRedisCache() (Redis), AddDistributedSqlServerCache() (SQL Server) u otra implementación persistente de IDistributedCache para cargas de trabajo de producción.