Serialización de la caché de tokens en MSAL.NET

Después de adquirir un token, la Biblioteca de autenticación de Microsoft (MSAL) lo almacena en caché. Las aplicaciones cliente públicas (aplicaciones de escritorio y móviles) deben intentar obtener un token de la memoria caché antes de adquirir un token mediante otro método. Los métodos de adquisición en aplicaciones cliente confidenciales administran ellos mismos la memoria caché. Este artículo describe la serialización predeterminada y personalizada de la caché de tokens en MSAL.NET.

Resumen rápido

La recomendación es:

  • Al escribir una aplicación de escritorio, use la caché de tokens multiplataforma, como se explica en Aplicaciones de escritorio.
  • No haga nada para aplicaciones móviles y para UWP. MSAL.NET proporciona almacenamiento seguro para la memoria caché.
  • En las aplicaciones web y las API web de ASP.NET Core, use Microsoft.Identity.Web como API de nivel superior. Obtendrá cachés de tokens y mucho más. Consulte Aplicaciones web y API web que no son de ASP.NET Core.
  • En los demás casos de aplicaciones web y API web:
    • Si solicita tokens para los usuarios de una aplicación de producción, use una caché de tokens distribuida (Redis, SQL Server, Azure Cosmos DB, memoria distribuida). Use los serializadores de caché de tokens disponibles en Microsoft.Identity.Web.TokenCache.
    • De lo contrario, si desea usar una caché en memoria:
      • Si solo usa AcquireTokenForClient, reutilice la instancia de aplicación cliente confidencial y no agregue un serializador, o cree una nueva aplicación cliente confidencial y habilite la AcquireTokenForClient.

        Una memoria caché compartida es más rápida porque no se serializa. Sin embargo, la memoria crecerá a medida que los tokens se almacenen en caché. El número de tokens es igual al número de inquilinos que el número de API de nivel inferior. Un token de aplicación tiene aproximadamente 2 KB de tamaño, mientras que los tokens para un usuario tienen un tamaño aproximado de 7 KB. Es excelente para el desarrollo o si tiene pocos usuarios.

      • Si desea usar una caché de tokens en memoria y controlar su tamaño y directivas de expulsión, use la opción de caché en memoria Microsoft.Identity.Web.

  • Si compila un SDK y quiere escribir su propio serializador de caché de tokens para aplicaciones cliente confidenciales, herede de Microsoft.Identity.Web.MsalAsbtractTokenCacheProvider e invalide los métodos y ReadCacheBytesAsync.

El paquete NuGet Microsoft.Identity.Web.TokenCache proporciona la serialización de la caché de tokens en la biblioteca Microsoft.Identity.Web.

Método de extensión Descripción
AddInMemoryTokenCaches Crea una memoria caché temporal en memoria para el almacenamiento y la recuperación de tokens. Las cachés de tokens en memoria son más rápidas que los demás tipos de caché, pero sus tokens no se conservan entre reinicios de la aplicación y no se puede controlar el tamaño de la caché. Las cachés en memoria son buenas para las aplicaciones que no requieren que los tokens se conserven entre reinicios de la aplicación. Use una caché de tokens en memoria en aplicaciones que participen en escenarios de autenticación de máquina a máquina, como servicios, demonios y otros que usan AcquireTokenForClient (la concesión de credenciales de cliente). Las cachés de tokens en memoria también son buenas para aplicaciones de ejemplo y durante el desarrollo de aplicaciones locales. Las versiones 1.19.0 y posteriores de Microsoft.Identity.Web comparten una caché de tokens en memoria entre todas las instancias de la aplicación.
AddSessionTokenCaches La caché de tokens está enlazada a la sesión de usuario. Esta opción no es conveniente si el token de identificador contiene muchas notificaciones, ya que la cookie se volvería demasiado grande.
AddDistributedTokenCaches La caché de tokens es un adaptador en la implementación de IDistributedCache de ASP.NET Core. Permite elegir entre una caché de memoria distribuida, una caché de Redis, una caché distribuida NCache o una caché de SQL Server. Para más información sobre las implementaciones de IDistributedCache, consulte IDistributedCache.

Caché de tokens en memoria

Este es un ejemplo de código que usa la caché en memoria en el método ConfigureServices de la clase Startup en una aplicación de ASP.NET Core:

#using Microsoft.Identity.Web
using Microsoft.Identity.Web;

public class Startup
{
 const string scopesToRequest = "user.read";
  
  public void ConfigureServices(IServiceCollection services)
  {
   // code before
   services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
           .AddMicrosoftIdentityWebApp(Configuration)
             .EnableTokenAcquisitionToCallDownstreamApi(new string[] { scopesToRequest })
                .AddInMemoryTokenCaches();
   // code after
  }
  // code after
}

AddInMemoryTokenCaches es adecuado en producción si solicita tokens solo de aplicación. Si usa tokens de usuario, considere la posibilidad de usar una caché de tokens distribuida.

El código de configuración de la caché de tokens es similar entre las aplicaciones web de ASP.NET Core y las API web.

Cachés de tokens distribuidos

Estos son ejemplos de posibles cachés distribuidas:

// or use a distributed Token Cache by adding
   services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
           .AddMicrosoftIdentityWebApp(Configuration)
             .EnableTokenAcquisitionToCallDownstreamApi(new string[] { scopesToRequest }
               .AddDistributedTokenCaches();

// Distributed token caches have a L1/L2 mechanism.
// L1 is in memory, and L2 is the distributed cache
// implementation that you will choose below.
// You can configure them to limit the memory of the 
// L1 cache, encrypt, and set eviction policies.
services.Configure<MsalDistributedTokenCacheAdapterOptions>(options => 
  {
    // Optional: Disable the L1 cache in apps that don't use session affinity
    //                 by setting DisableL1Cache to 'false'.
    options.DisableL1Cache = false;
    
    // Or limit the memory (by default, this is 500 MB)
    options.sizeLimit = 1024 * 1024 * 1024, // 1 GB

    // You can choose if you encrypt or not encrypt the cache
    options.Encrypt = false;

    // And you can set eviction policies for the distributed
    // cache.
    options.SlidingExpiration = TimeSpan.FromHours(1);
  }

// Then, choose your implementation of distributed cache
// -----------------------------------------------------

// For instance, the distributed in-memory cache (not cleared when you stop the app)
services.AddDistributedMemoryCache();

// Or a Redis cache
// Requires the Microsoft.Extensions.Caching.StackExchangeRedis NuGet package
services.AddStackExchangeRedisCache(options =>
{
 options.Configuration = "localhost";
 options.InstanceName = "SampleInstance";
});

// You can even decide if you want to repair the connection
// with Redis and retry on Redis failures. 
services.Configure<MsalDistributedTokenCacheAdapterOptions>(options => 
{
  options.OnL2CacheFailure = (ex) =>
  {
    if (ex is StackExchange.Redis.RedisConnectionException)
    {
      // action: try to reconnect or something
      return true; //try to do the cache operation again
    }
    return false;
  };
});

// Or even a SQL Server token cache
// Requires the Microsoft.Extensions.Caching.SqlServer NuGet package
services.AddDistributedSqlServerCache(options =>
{
 options.ConnectionString = _config["DistCache_ConnectionString"];
 options.SchemaName = "dbo";
 options.TableName = "TestCache";
});

// Or an Azure Cosmos DB cache
// Requires the Microsoft.Extensions.Caching.Cosmos NuGet package
services.AddCosmosCache((CosmosCacheOptions cacheOptions) =>
{
    cacheOptions.ContainerName = Configuration["CosmosCacheContainer"];
    cacheOptions.DatabaseName = Configuration["CosmosCacheDatabase"];
    cacheOptions.ClientBuilder = new CosmosClientBuilder(Configuration["CosmosConnectionString"]);
    cacheOptions.CreateIfNotExists = true;
});

Para más información, consulte:

El uso de la caché distribuida se incluye en el tutorial de aplicaciones web de ASP.NET Core en la fase de la caché de tokens 2-2.

Supervisión de las relaciones de aciertos de caché y el rendimiento de la caché

MSAL expone métricas importantes como parte del objeto AuthenticationResult.AuthenticationResultMetadata. Puede registrar estas métricas para evaluar el estado de la aplicación.

Métrica Significado ¿Cuándo se debe desencadenar una alarma?
DurationTotalInMs Tiempo total invertido en MSAL, incluidas las llamadas de red y la caché. Alarma sobre la latencia alta general (> 1 segundo). El valor depende del origen del token. Desde la caché: un acceso a la caché. Desde Azure Active Directory (Azure AD): dos accesos de caché más una llamada HTTP. La primera llamada (por proceso) llevará más tiempo debido a una llamada HTTP adicional.
DurationInCacheInMs Tiempo invertido en cargar o guardar la caché de tokens, que el desarrollador de la aplicación personaliza (por ejemplo, se guarda en Redis). Alarma sobre aumentos.
DurationInHttpInMs Tiempo dedicado a realizar llamadas HTTP a Azure AD. Alarma sobre aumentos.
TokenSource Origen del token. Los tokens se recuperan de la caché mucho más rápido (por ejemplo, ~100 ms frente a ~700 ms). Se puede usar para supervisar y enviar una alarma sobre la proporción de aciertos de caché. Se usa con DurationTotalInMs.
CacheRefreshReason Motivo para capturar el token de acceso del proveedor de identidades. Se usa con TokenSource.

Pasos siguientes

Los ejemplos siguientes ilustran la serialización de la caché de tokens.

Muestra Plataforma Descripción
active-directory-dotnet-desktop-msgraph-v2 Escritorio (WPF) Aplicación .NET de Windows Desktop (WPF) que llama a Microsoft Graph API. Diagram that shows a topology with a desktop app client flowing to Azure Active Directory by acquiring a token interactively and to Microsoft Graph.
active-directory-dotnet-v1-to-v2 Escritorio (consola) Conjunto de soluciones de Visual Studio que ilustran la migración de aplicaciones de Azure AD v1.0 (mediante ADAL.NET) a las aplicaciones de la plataforma de identidad de Microsoft (mediante MSAL.NET). En concreto, vea Migración de la caché de tokens y Caché de tokens cliente confidencial.
ms-identity-aspnet-webapp-openidconnect ASP.NET (net472) Ejemplo de serialización de caché de tokens en una aplicación MVC de ASP.NET (mediante MSAL.NET). En concreto, vea MsalAppBuilder.