Serialização de cache de token

Depois que Biblioteca do Microsoft Authenticator (MSAL) adquire um token, ele armazena esse token em cache. Aplicativos cliente públicos (aplicativos móveis e desktop) devem tentar obter um token do cache antes de adquirir um token por outro método. Métodos de aquisição em aplicativos cliente confidenciais gerenciam o cache por conta própria. Este artigo discute a serialização padrão e personalizada do cache de token em MSAL.NET.

Resumo

A recomendação é:

O pacote NuGet Microsoft.Identity.Web.TokenCache fornece serialização do cache de tokens na biblioteca Microsoft.Identity.Web. A biblioteca fornece integração com ASP.NET Core e ASP.NET Clássico, e suas abstrações podem ser usadas para impulsionar outras estruturas de API ou aplicativo Web.

Note

Os exemplos abaixo são para ASP.NET Core. Para ASP.NET o código é semelhante, consulte o exemplo de ms-identity-aspnet-wepapp-openidconnect aplicativo Web para uma implementação de referência.

Método de extensão Description
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 outros tipos de cache, mas seus tokens não são persistidos 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 autenticação de máquina para máquina, como serviços, daemons e outros que usam AcquireTokenForClient (a concessão de credenciais do cliente). Os 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 tokens na memória entre todas as instâncias da aplicação.
AddSessionTokenCaches O cache de token está associado à sessão do usuário. Essa opção não será ideal se o token de ID contiver muitas declarações, pois 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. Para obter detalhes sobre as IDistributedCache implementações, consulte o cache de memória distribuída.

Cache de token na memória

Aqui está 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;

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 será 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 entre aplicativos Web ASP.NET Core e APIs Web.

Caches distribuídos de token

Aqui estão 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 'true'.
    options.DisableL1Cache = false;
    
    // Or limit the memory (by default, this is 500 MB)
    options.L1CacheOptions.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
// -----------------------------------------------------

// good for prototyping and testing, but this is NOT persisted and it is NOT distributed - do not use in production
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:

O uso do cache distribuído é destacado no tutorial do aplicativo Web ASP.NET Core, no cache de token da fase 2-2.

Monitorar as taxas de acerto de cache e o desempenho do cache

A MSAL expõe métricas importantes como parte do objeto AuthenticationResult.AuthenticationResultMetadata . Você pode registrar essas métricas para avaliar a integridade do aplicativo.

Métrica Meaning Quando disparar um alarme?
DurationTotalInMs Tempo total gasto na MSAL, incluindo chamadas de rede e cache. Alarme para latência geral alta (> 1 segundo). O valor depende da origem do token. Do cache: um acesso de cache. De Microsoft Entra ID: dois acessos de cache mais uma chamada HTTP. A primeira chamada (por processo) leva 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, salve no Redis). Alarme em picos.
DurationInHttpInMs Tempo gasto fazendo chamadas HTTP para Microsoft Entra ID. Alarme em picos.
TokenSource Origem do token. Os tokens são recuperados do cache muito mais rápido (por exemplo, ~100 ms versus ~700 ms). Pode ser usado para monitorar e emitir alerta sobre a 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.

Aproximações de tamanho

Ao usar um cache de token, é importante considerar o tamanho potencial do cache, especialmente para aplicativos altamente disponíveis e distribuídos. Quando os usuários fizerem logon, haverá uma entrada de cache para cada usuário, com cerca de 7 KB de tamanho. O tamanho será maior se você estiver chamando várias APIs downstream. Para a autenticação de serviço a serviço, haverá uma entrada de cache para cada locatário e API downstream, com cerca de 2 KB.

Estimativas detalhadas são listadas abaixo.

Fluxos de aplicativo (AcquireTokenForClient, AcquireTokenForManagedIdentity)

  • Somente os tokens de acesso são armazenados em cache. Um token com cerca de 2 a 3 KB quando persistido. Haverá 1 token por ID do cliente de aplicativo * locatários * recursos downstream. Por exemplo, um aplicativo multilocatário que atende a 1000 locatários e precisa de tokens para Graph e SharePoint usará: 3KB * 1000 * 2, ou seja, aproximadamente 6 MB.

Site chamando uma API Web downstream (AcquireTokenByAuthCode)

  • Tokens de acesso – 4KB; 1 token por ID do cliente do aplicativo * usuário * locatário * recurso de destino.
  • Token de atualização – 2KB; 1 token por ID do aplicativo cliente * usuário.
  • Token de identificação – 2KB; 1 token por ID do aplicativo cliente * usuário * número de locatários nos quais esse usuário faz logon.

Note

Recomendamos fortemente usar as APIs de nível superior de Microsoft.Identity.Web para isso, e não MSAL diretamente. As considerações de cache são as mesmas.

API da Web chamando outra API da Web (AcquireTokenOnBehalfOf)

Igual ao cenário do site, mas haverá um nó para cada sessão, não para cada usuário. Por padrão, a MSAL identifica uma sessão fazendo o hash da asserção upstream, mas isso pode ser alterado. Consulte processos OBO de execução prolongada.

Note

Recomendamos fortemente usar as APIs de nível superior de Microsoft.Identity.Web para isso, e não MSAL diretamente. As considerações de cache são as mesmas.

Tipos de cache de token

MSAL.NET opera com dois tipos de caches de token : usuário e aplicativo.

O cache de token de aplicativo que contém tokens de acesso para este aplicativo. Ele é mantido e atualizado silenciosamente ao chamar AcquireTokenForClient.

O cache de token de usuário contém tokens de ID, tokens de acesso e tokens de atualização para contas com as quais MSAL.NET interage. Ela é usada e atualizada silenciosamente, se necessário, ao chamar AcquireTokenSilent. Ele é atualizado por cada método de aquisição de token, com exceção de AcquireTokenForClient , que usa apenas o cache do aplicativo.

Próximas Etapas 

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

Amostra Platform Description
active-directory-dotnet-desktop-msgraph-v2 Desktop (WPF) Aplicativo .NET para desktop do Windows (WPF) que chama a API do Microsoft Graph. Diagrama que mostra uma topologia com um cliente de aplicativo para desktop que se conecta ao Microsoft Entra ID para obter um token de forma interativa e ao Microsoft Graph.
active-directory-dotnet-v1-to-v2 Área de trabalho (console) Conjunto de soluções Visual Studio que ilustram a migração de aplicativos Azure AD v1.0 (usando a ADAL.NET) para plataforma de identidade da Microsoft aplicativos (usando MSAL.NET).
ms-identity-aspnet-webapp-openidconnect ASP.NET (net472) Exemplo de serialização de cache de token em um aplicativo ASP.NET MVC (usando MSAL.NET).