Serialização do cache de token na MSAL.NET

Após que a MSAL (Biblioteca de Autenticação da Microsoft) adquire um token, ela o armazena em cache. Os aplicativos cliente públicos (aplicativos móveis e desktop) devem tentar obter um token da cache antes de adquirir um token por outro método. Os métodos de aquisição em aplicativos cliente confidenciais gerenciam o cache por conta própria. Este artigo aborda a serialização padrão e personalizada do cache de token na MSAL.NET.

Resumo rápido

A recomendação é:

  • Ao escrever um aplicativo de área de trabalho, use o cache de token de plataforma cruzada, conforme explicado em Aplicativos de desktop.
  • Não faça nada para Aplicativos móveis e UWP. MSAL.NET fornece armazenamento seguro para o cache.
  • Em aplicativos Web do ASP.NET Core e APIs Web, use o Microsoft.Identity.Web como uma API de alto nível. Você obterá caches de token e muito mais. Confira APIs Web e aplicativos Web do ASP.NET Core.
  • Nos outros casos de aplicativos Web e APIs da Web:
    • Se você solicitar tokens para usuários em um aplicativo de produção, use um cache de token distribuído (Redis, SQL Server, Azure Cosmos DB, memória distribuída). Use serializadores de cache de token de Microsoft.Identity.Web.TokenCache.
    • Caso contrário, se você quiser usar um cache na memória
      • Se você estiver usando apenasAcquireTokenForClient, reutilizar a instância de aplicativo cliente confidencial e não adicionar um serializador ou criar um novo aplicativo cliente confidencial e habilitar a opção de AcquireTokenForClient.

        Um cache compartilhado é mais rápido porque não é serializado. No entanto, a memória aumentará à medida que os tokens são armazenados em cache. O número de tokens é igual ao número de locatários vezes o número de APIs de downstream. Um token de aplicativo tem cerca de 2 KB de tamanho, enquanto os tokens para um usuário têm cerca de 7 KB de tamanho. É ótimo para o desenvolvimento, ou se você tiver poucos usuários.

      • Se você quiser usar um cache de token na memória e controlar suas políticas de remoção e tamanho, use a opção de cache Microsoft.Identity.Web em memória.

  • Se você criar um SDK e quiser gravar seu próprio serializador de cache de token para aplicativos cliente confidenciais, herde de Microsoft.Identity.Web.MsalAsbtractTokenCacheProvider e substitua os métodos e ReadCacheBytesAsync.

O pacote NuGet Microsoft.Identity.Web.TokenCache fornece serialização de cache de token na bibliotecaMicrosoft.Identity.Web.

Método de extensão Descrição
AddInMemoryTokenCaches Cria um cache temporário na memória para armazenamento e recuperação de token. Os caches de token na memória são mais rápidos do que os outros tipos de cache, mas seus tokens não são persistentes entre as reinicializações do aplicativo e você não pode controlar o tamanho do cache. Os caches na memória são bons para aplicativos que não exigem que os tokens persistam entre as reinicializações do aplicativo. Use um cache de token na memória em aplicativos que participam de cenários de auth de computador para computador, como serviços, daemons e outros que usam AcquireTokenForClient (a concessão de credenciais do cliente). Caches de token na memória também são bons para aplicativos de exemplo e durante o desenvolvimento de aplicativos locais. As versões 1.19.0+ do Microsoft.Identity.Web compartilham um cache de token na memória em todas as instâncias de aplicativo.
AddSessionTokenCaches O cache do token está associado à sessão do usuário. Essa opção não será ideal se o token de ID contiver muitas declarações, porque o cookie se tornará muito grande.
AddDistributedTokenCaches O cache de token é um adaptador em relação à implementação ASP.NET Core IDistributedCache dados. Ele permite que você escolha entre um cache de memória distribuída, um cache Redis, um NCache distribuído ou um cache SQL Server dados. Para detalhes sobre as implementações de IDistributedCache, confira IDistributedCache.

No cache de token de memória

Veja um exemplo de código que usa o cache na memória no método ConfigureServices da classe Startup em um aplicativo 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
}

AddInMemoryTokenCachesserá adequado em produção se você solicitar tokens somente de aplicativo. Se você usar tokens de usuário, considere usar um cache de token distribuído.

O código de configuração do cache de token é semelhante ASP.NET Core aplicativos Web e APIs Web.

Caches de token distribuídos

Vejamos exemplos de possíveis caches distribuídos:

// 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 obter mais informações, consulte:

Seu uso de cache distribuído é apresentado no Tutorial de aplicativo Web do ASP.NET Core na fase Cache de token 2-2.

Monitorar taxas de ocorrência de cache e desempenho do cache

A MSAL expões métricas importantes como parte do objeto AuthenticationResult.AuthenticationResultMetadata. Você pode registrar essas métricas para avaliar a saúde do seu aplicativo.

Métrica Significado Quando disparar um alarme?
DurationTotalInMs Tempo total gasto na MSAL, incluindo chamadas de rede e cache. Alarme em alta latência geral (> 1 segundo). O valor depende da origem do token. Do cache: um acesso de cache. Do Azure Active Directory (Azure AD): dois acessos de cache mais uma chamada HTTP. A primeira chamada (por processo) levará mais tempo devido a uma chamada HTTP extra.
DurationInCacheInMs Tempo gasto carregando ou salvando o cache de token, que é personalizado pelo desenvolvedor do aplicativo (por exemplo, salvar no Redis). Alarme em picos.
DurationInHttpInMs Tempo gasto fazendo chamadas HTTP para o Azure Active Directory. Alarme em picos.
TokenSource Origem do token. Os tokens são recuperados do cache muito mais rapidamente (por exemplo, ~100 ms versus ~700 ms). Pode ser usado para monitorar e inserir alarme na taxa de acertos do cache. Usar com o DurationTotalInMs.
CacheRefreshReason Motivo para buscar o token de acesso do provedor de identidade. Usar com o TokenSource.

Próximas etapas

Os exemplos a seguir ilustram a serialização do cache de token.

Amostra Plataforma Descrição
active-directory-dotnet-desktop-msgraph-v2 Desktop (WPF) Aplicativo Windows Desktop .NET (WPF) que chama a API do Microsoft Graph. 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 Desktop (Console) Conjunto de soluções do Visual Studio que ilustram a migração de aplicativos do Azure AD v 1.0 (usando ADAL.NET) para aplicativos da plataforma Microsoft Identity (usando MSAL.NET). Em específico, confira Migração do cache de Token e Cache de token de cliente confidencial.
ms-identity-aspnet-webapp-openidconnect ASP.NET (net472) Exemplo de serialização de cache de token em um aplicativo MVC ASP.NET (usando MSAL.NET). Confira, em específico MsalAppBuilder.