I am trying to add Azure Redis Cache to my .NET 8 api. I added the connectionString and added the code as:
services.AddStackExchangeRedisCache(
options =>
{
options.Configuration = builder.Configuration.GetConnectionString("RedisCache");
options.InstanceName = builder.Environment.EnvironmentName;
})
.AddDistributedMemoryCache();
This is working when I added my password in the connectionString. But I do not want to do this, I want to use Entra ID authentication. So I have enabled the option, and also selected the web app (also in azure) which needs to use it. Access Policy as data owner. But when I leave out the password, I am getting an error:
StackExchange.Redis.RedisConnectionException: 'The message timed out in the backlog attempting to send because no connection became available (5000ms) - Last Connection Exception: AuthenticationFailure on tsg-pas-dev-redis.redis.cache.windows.net:6380/Interactive, Flushed/ComputeResult, last: ECHO, origin: SetResult, outstanding: 0, last-read: 0s ago, last-write: 0s ago, keep-alive: 60s, state: ConnectedEstablishing, mgr: 9 of 10 available, last-heartbeat: never, global: 0s ago, v: 2.6.122.38350, command=SET, timeout: 5000, inst: 12, qu: 1, qs: 0, aw: False, bw: SpinningDown, rs: ReadAsync, ws: Flushed, in: 0, last-in: 0, cur-in: 0, sync-ops: 1, async-ops: 1, serverEndpoint: tsg-pas-dev-redis.redis.cache.windows.net:6380, conn-sec: 0.23, aoc: 0, mc: 1/1/0, mgr: 10 of 10 available, clientName: DBSX1Y6-54977(SE.Redis-v2.6.122.38350), IOCP: (Busy=1,Free=999,Min=8,Max=1000), WORKER: (Busy=1,Free=32766,Min=8,Max=32767), POOL: (Threads=15,QueuedItems=0,CompletedItems=347,Timers=3), v: 2.6.122.38350 (Please take a look at this article for some common client-side issues that can cause timeouts: https://stackexchange.github.io/StackExchange.Redis/Timeouts)'
Exception: Error: NOAUTH Authentication required. Verify if the Redis password provided is correct. Attempted command: ECHO
Any clue what I am missing? I remember with one of the other services, I had to do something in the main, to fetch/initialize the token... but no clue if it is related or not.
-- EDIT:
After the answer below I made a small change so I can still use IDistributedCache, because locally i can still use MemoryCache:
public static void AddDistributedCache(this IServiceCollection services, WebApplicationBuilder builder)
{
if (builder.Configuration["UseMemoryCache"]?.Equals("yes", StringComparison.OrdinalIgnoreCase) ?? true)
{
services.AddDistributedMemoryCache();
}
else
{
services.AddStackExchangeRedisCache(options =>
{
options.InstanceName = builder.Environment.EnvironmentName;
options.ConnectionMultiplexerFactory = () => ConnectionMultiplexerFactory(builder);
})
.AddDistributedMemoryCache();
}
}
private static async Task<IConnectionMultiplexer> ConnectionMultiplexerFactory(WebApplicationBuilder builder)
{
var configurationOptions = await ConfigurationOptions.Parse(builder.Configuration.GetConnectionString("RedisCache")!)
.ConfigureForAzureWithTokenCredentialAsync("XXXX", new DefaultAzureCredential());
var connectionMultiplexer = await ConnectionMultiplexer.ConnectAsync(configurationOptions);
return connectionMultiplexer;
}
The XXX needs to come from appsettings, allthough I do not understand yet why I need it. And not very handy when using multiple apps on the same redis ache instance yet I guess... But at least no passwords :)
The good thing about this is that I can easily switch and also do not have to worry about multiplexer getDatabase etc...
Based on the documentation available
here, in order to use Entra ID authentication, you would need to useMicrosoft.Azure.StackExchangeRedisNuget package.Code sample for the same is available here: https://github.com/Azure/Microsoft.Azure.StackExchangeRedis/tree/main/sample.
From this link, sample code to use
DefaultAzureCredential: