Implement a distributed token cache for ASP.NET Core apps with Azure Cosmos DB
Tags: azure, dotnet, security, webdev
Published: 2020-07-28 17:08:59

On a previous [blog post](https://developer.microsoft.com/en-us/identity/blogs/how-to-build-a-blazor-web-app-with-azure-active-directory-authentication-and-microsoft-graph/) we examined the steps necessary to add authentication to a Blazor Server app using the latest [Microsoft.Identity.Web](https://github.com/AzureAD/microsoft-identity-web/wiki/token-cache-serialization) library. Everything worked as expected and we were able to authenticate against Azure AD, acquire an access token and retrieve data from Microsoft Graph. However, there is one small issue with the current implementation of our code. Our token cache is configured to run in memory. This is great for quickly testing the app but presents a few issues once we decide to deploy and run the app in production. The app can’t scale as the token cache is only available to the local instance and if, for whatever reason, the app restarts, all tokens in cache will be wiped out along with our cache.

## Prerequisites
You need to have the following installed or available to you
-	An Azure AD tenant
-	.NET Core 3.1 or later
-	An Azure Cosmos DB instance or the [local emulator](https://docs.microsoft.com/en-us/azure/cosmos-db/local-emulator)
-	Visual Studio 2019 or Visual Studio Code

## Implementing a distributed cache
Luckily for us, the Microsoft.Identity.Web library comes with built-in support for distributed caches. In fact, it only takes one line of code to configure it. This makes it extremely straightforward to create a robust solution right out of the box. The [official documentation](https://github.com/AzureAD/microsoft-identity-web/wiki/token-cache-serialization) provides the following options for setting up a distributed cache:

-	SQL Server
-	Redis Cache
-	NCache

However, since all these cache providers implement the [IDistributedCache](https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed?view=aspnetcore-3.1#distributed-memory-cache) interface, my assumption is that any provider that implements that same interface can be used with Microsoft.Identity.Web. And as luck will have it, there is already a [provider for Cosmos DB](https://github.com/Azure/Microsoft.Extensions.Caching.Cosmos) (in preview) that implements this interface. Therefore, my assumption is that using this, our application should work straight out of the box without any code changes. Let’s do it!

First, we need to install the appropriate NuGet package. Use the option that works best for you (CLI, PowerShell, Package Manager etc.) to install the [Microsoft.Extensions.Caching.Cosmos](https://www.nuget.org/packages/Microsoft.Extensions.Caching.Cosmos) package

![NuGet install](https://dev-to-uploads.s3.amazonaws.com/i/9m0v2rtc4a6vdjuxju7l.png)

With the NuGet package installed, we need to edit the appsettings.json file and add the following parameters that will be used to instantiate our Cosmos DB cache which runs locally via the emulator:

```
"CosmosCacheContainer": "TokenCache",
"CosmosCacheDatabase": "BlazorCache",
"CosmosConnectionString": “AccountEndpoint=https://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==",
```

> NOTE: note that the `AccountKey` on the connection string is a well know key that is common for anyone using the emulator, hence the reason I didn’t omit it here. _#security_

The one last thing we need to do is update our middleware code in `Startup.cs` to register the Cosmos DB cache and make it available to our authentication middleware. Paste the following code:

```
services.AddCosmosCache((CosmosCacheOptions cacheOptions) =>
{
    cacheOptions.ContainerName = Configuration["CosmosCacheContainer"];
    cacheOptions.DatabaseName = Configuration["CosmosCacheDatabase"];
    cacheOptions.ClientBuilder = new CosmosClientBuilder(Configuration["CosmosConnectionString"]);
    cacheOptions.CreateIfNotExists = true;
});

services.AddMicrosoftWebAppAuthentication(Configuration)
    .AddMicrosoftWebAppCallsWebApi(Configuration, new string[] { "User.Read", "Mail.Read" })
.AddDistributedTokenCaches();
```
Running the code again, we can see that upon authentication, our Cosmos DB cache gets populated with our token information that can be used later by our app to retrieve the data from MS Graph:

![CosmosDB cache](https://dev-to-uploads.s3.amazonaws.com/i/7nuzwbzg3ml5xbk6xesu.png)

## Video recording
There is also a [video recording](https://www.twitch.tv/videos/686272926) where we (Christos and JP) show you how we put this all together live on Twitch! 

![Twitch stream](https://dev-to-uploads.s3.amazonaws.com/i/m215wrrkgd0eqelkrusi.png)

The Identity Dev Advocates team streams on Tuesdays at 7am PT and Thursdays at 8am PT on [Twitch](https://twitch.tv/425Show). We cover all things identity and we like to bring guests and customers on the air to learn how they use our tools and platform to build their solutions. 

If you want to get involved or have any questions make sure to reach out to [Christos Matskas](https://twitter.com/christosmatskas) or [JP](https://twitter.com/AzureAndChill)

## Summary
As you can see, the latest Microsoft.Identity.Web makes it very easy to work with distributed caches in a ‘plug-n-play’ mode. And, as long as, a cache provider implements the IDistributedCache interface, you can use any custom cache with your ASP.NET Core app.