トークン キャッシュのシリアル化

Microsoft Authentication Library (MSAL) は、トークンを取得した後、そのトークンをキャッシュします。 パブリック クライアント アプリケーション (デスクトップ アプリとモバイル アプリ) は、別の方法でトークンを取得する前に、キャッシュからトークンを取得しようとする必要があります。 機密クライアント アプリケーションの取得方法は、キャッシュ自体を管理します。 この記事では、MSAL.NET でのトークン キャッシュの既定のシリアル化とカスタムシリアル化について説明します。

まとめ

推奨事項は次のとおりです。

  • モバイル アプリを作成する場合、キャッシュは MSAL によって既に事前に構成されています。
  • デスクトップ アプリケーションを記述するときは、 デスクトップ アプリで説明されているようにクロスプラットフォーム トークン キャッシュを使用します。
  • 新しい機密クライアント アプリケーション (Web アプリWeb API、または サービス間またはデーモン アプリ) を作成するときは、高水準 API として Microsoft.Identity.Web を使用します。 ASP.NET Core、ASP.NET クラシックとの統合を提供し、スタンドアロンでも動作します。
  • MSAL.NET を直接利用する既存の機密クライアント アプリケーションは、引き続きこれを行うことができます。
  • Web アプリWeb API では、制約付きメモリ キャッシュと組み合わせて分散トークン キャッシュ (Redis、SQL Server、Azure Cosmos DBなど) を使用する必要があります。
  • 保存時の暗号化は、必要に応じて ASP.NET Core Data Protection を使用して構成できます。
  • Web アプリ は、セッション Cookie に依存する場合もあります。ただし、Cookie サイズのため、このオプションは推奨されません。
  • サービス間アプリとデーモン アプリ は、メモリ キャッシュのみに依存できます。 アプリが多数のテナントにサービスを提供している場合は、削除ポリシーを構成します。
  • マネージド ID トークンはメモリ内でのみキャッシュされます。

Microsoft.Identity.Web.TokenCache NuGet パッケージは、Microsoft.Identity.Web ライブラリ内でトークン キャッシュのシリアル化を提供します。 ライブラリは、ASP.NET Coreと ASP.NET Classic の両方との統合を提供し、その抽象化を使用して他の Web アプリまたは API フレームワークを駆動できます。

Note

次の例は、ASP.NET Core用です。 ASP.NET の場合、コードは同様です。参照実装については、ms-identity-aspnet-wepapp-openidconnect Web アプリのサンプルを参照してください。

拡張メソッド 説明
AddInMemoryTokenCaches トークンの格納と取得のためにメモリ内に一時キャッシュを作成します。 メモリ内トークン キャッシュは他のキャッシュの種類よりも高速ですが、そのトークンはアプリケーションの再起動の間に保持されず、キャッシュ サイズを制御することはできません。 メモリ内キャッシュは、アプリの再起動の間にトークンを保持する必要がないアプリケーションに適しています。 サービス、デーモン、 AcquireTokenForClient (クライアント資格情報付与) を使用する他のサービスなどのコンピューター間認証シナリオに参加するアプリでメモリ内トークン キャッシュを使用します。 メモリ内トークン キャッシュは、サンプル アプリケーションやローカル アプリ開発時にも適しています。 Microsoft。Identity.Web バージョン 1.19.0 以降では、すべてのアプリケーション インスタンスでメモリ内トークン キャッシュが共有されます。
AddSessionTokenCaches トークン キャッシュはユーザー セッションにバインドされます。 このオプションは、ID トークンに多くの要求が含まれている場合は理想的ではありません。これは、Cookie が大きすぎるためです。
AddDistributedTokenCaches トークン キャッシュは、ASP.NET Core IDistributedCache実装に対するアダプターです。 これにより、分散メモリ キャッシュ、Redis キャッシュ、分散 NCache、またはSQL Server キャッシュのいずれかを選択できます。 IDistributedCache実装の詳細については、「分散メモリ キャッシュ」を参照してください。

メモリ内トークン キャッシュ

ASP.NET Core アプリケーションの Startup クラスの ConfigureServices メソッドでメモリ内キャッシュを使用するコードの例を次に示します。

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 は、アプリ専用トークンを要求する場合に運用環境に適しています。 ユーザー トークンを使用する場合は、分散トークン キャッシュの使用を検討してください。

トークン キャッシュ構成コードは、ASP.NET Core Web アプリと Web API の間で似ています。

分散トークン キャッシュ

考えられる分散キャッシュの例を次に示します。

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

詳細については、以下を参照してください:

分散キャッシュの使用方法は、フェーズ 2-2 トークン キャッシュASP.NET Core Web アプリのチュートリアルで紹介されています。

キャッシュ ヒット率とキャッシュ パフォーマンスを監視する

MSAL は、 AuthenticationResult.AuthenticationResultMetadata オブジェクトの一部として重要なメトリックを公開します。 これらのメトリックをログに記録して、アプリケーションの正常性を評価できます。

Metric Meaning アラームをトリガーするタイミング
DurationTotalInMs ネットワーク呼び出しとキャッシュを含む、MSAL で費やされた合計時間。 全体的な待機時間が長い場合のアラーム (> 1 秒)。 値はトークン ソースによって異なります。 キャッシュから: 1 つのキャッシュ アクセス。 Microsoft Entra IDから: 2 つのキャッシュ アクセスと 1 つの HTTP 呼び出し。 最初の呼び出し (プロセスごと) は、1 つの余分な HTTP 呼び出しのために時間がかかります。
DurationInCacheInMs トークン キャッシュの読み込みまたは保存に費やされた時間。これはアプリ開発者によってカスタマイズされます (たとえば、Redis に保存)。 スパイク時のアラーム。
DurationInHttpInMs Microsoft Entra IDへの HTTP 呼び出しの作成に費やされた時間。 スパイク時のアラーム。
TokenSource トークンのソース。 トークンはキャッシュからはるかに高速に取得されます (たとえば、約 100 ミリ秒と約 700 ミリ秒)。 キャッシュ ヒット率を監視およびアラームするために使用できます。 DurationTotalInMs で使用します。
CacheRefreshReason ID プロバイダーからアクセストークンを取得する理由。 TokenSource で使用します。

サイズの近似値

トークン キャッシュを使用する場合は、キャッシュの潜在的なサイズ (特に高可用性および分散アプリケーションの場合) を考慮することが重要です。 ユーザーがログインすると、サイズが約 7 KB の各ユーザーのキャッシュ エントリが表示されます。 複数のダウンストリーム API を呼び出す場合、サイズは大きくなります。 サービス間認証の場合、各テナントとダウンストリーム API のキャッシュ エントリが約 2 KB のサイズになります。

詳細な見積もりを次に示します。

アプリケーション フロー (AcquireTokenForClientAcquireTokenForManagedIdentity)

  • アクセス トークンのみがキャッシュされます。 永続化した場合、1トークンあたり約2~3KB。 アプリ クライアント ID * テナント * ダウンストリーム リソースごとに 1 つのトークンがあります。 たとえば、1000 テナントにサービスを提供し、Graph と SharePoint のトークンを必要とするマルチテナント アプリでは、3 KB * 1000 * 2 つまり約 6 MB が使用されます。

ダウンストリーム Web API を呼び出す Web サイト (AcquireTokenByAuthCode)

  • アクセス トークン – 4 KB; アプリ クライアント ID * ユーザー * テナント * ダウンストリーム リソースごとに 1 つのトークン。
  • 更新トークン – 2 KB; クライアント アプリ ID * ユーザーごとに 1 つのトークン。
  • ID トークン – 2 KB; クライアント アプリ ID あたり 1 トークン * ユーザー * そのユーザーがログインするテナントの数。

Note

この用途では、MSAL を直接使用するのではなく、Microsoft.Identity.Web で提供される、より高レベルの API を使用することを強くお勧めします。 キャッシュに関する考慮事項は同じです。

他の Web API を呼び出す Web API (AcquireTokenOnBehalfOf)

Web サイトのシナリオと同じですが、ユーザーごとにではなく、セッションごとに 1 つのノードが存在します。 既定では、MSAL はアップストリーム アサーションをハッシュすることによってセッションを識別しますが、これは変更できます。 実行時間の長い OBO プロセスを参照してください。

Note

この目的には、MSAL を直接使用するのではなく、Microsoft.Identity.Web の高レベル API を使用することを強くお勧めします。 キャッシュに関する考慮事項は同じです。

トークン キャッシュの種類

MSAL.NET は、ユーザーアプリケーションの 2 種類のトークン キャッシュで動作します。

この アプリケーション のアクセス トークンを保持するアプリケーション トークン キャッシュ。 AcquireTokenForClient を呼び出すときは、サイレントモードで維持および更新されます。

ユーザー トークン キャッシュには、MSAL.NET がやり取りするアカウントの ID トークン、アクセス トークン、および更新トークンが保持されます。 AcquireTokenSilent を呼び出すときに必要に応じて、サイレントモードで使用および更新されます。 これは、アプリケーション キャッシュのみを使用する AcquireTokenForClient を除き、各トークン取得メソッドによって更新されます。

次のステップ

次のサンプルは、トークン キャッシュのシリアル化を示しています。

Sample Platform 説明
active-directory-dotnet-desktop-msgraph-v2 デスクトップ (WPF) Microsoft Graph API を呼び出す Windows デスクトップ .NET (WPF) アプリケーション デスクトップ アプリ クライアントが対話形式でトークンを取得して Microsoft Entra ID に接続し、Microsoft Graph にも接続するトポロジを示す図。
active-directory-dotnet-v1-to-v2 デスクトップ (コンソール) ADAL.NET を使用する Azure AD v1.0 アプリケーションから、MSAL.NET を使用する Microsoft ID プラットフォーム アプリケーションへの移行を示す一連の Visual Studio ソリューション。
ms-identity-aspnet-webapp-openidconnect ASP.NET (net472) (MSAL.NET を使用した) ASP.NET MVC アプリケーションでのトークン キャッシュのシリアル化の例。