diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props
index ccd69b9600..60b48241fc 100644
--- a/src/Directory.Packages.props
+++ b/src/Directory.Packages.props
@@ -7,7 +7,7 @@
-
+
@@ -34,6 +34,7 @@
+
@@ -46,7 +47,7 @@
-
+
diff --git a/src/Service/Azure.DataApiBuilder.Service.csproj b/src/Service/Azure.DataApiBuilder.Service.csproj
index 5cf762ca57..d0478b83ed 100644
--- a/src/Service/Azure.DataApiBuilder.Service.csproj
+++ b/src/Service/Azure.DataApiBuilder.Service.csproj
@@ -64,6 +64,7 @@
+
diff --git a/src/Service/Startup.cs b/src/Service/Startup.cs
index 333bf57234..39fc0e29b0 100644
--- a/src/Service/Startup.cs
+++ b/src/Service/Startup.cs
@@ -3,6 +3,8 @@
using System;
using System.IO.Abstractions;
+using System.Linq;
+using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
@@ -435,7 +437,7 @@ public void ConfigureServices(IServiceCollection services)
else
{
// NOTE: this is done to reuse the same connection multiplexer for both the cache and backplane
- Task connectionMultiplexerTask = ConnectionMultiplexer.ConnectAsync(level2CacheOptions.ConnectionString);
+ Task connectionMultiplexerTask = CreateConnectionMultiplexerAsync(level2CacheOptions.ConnectionString);
fusionCacheBuilder
.WithSerializer(new FusionCacheSystemTextJsonSerializer())
@@ -470,6 +472,33 @@ public void ConfigureServices(IServiceCollection services)
services.AddControllers();
}
+ ///
+ /// Creates a ConnectionMultiplexer for Redis with support for Azure Entra authentication.
+ ///
+ /// The Redis connection string.
+ /// A task that represents the asynchronous operation. The task result contains the connected IConnectionMultiplexer.
+ private static async Task CreateConnectionMultiplexerAsync(string connectionString)
+ {
+ ConfigurationOptions options = ConfigurationOptions.Parse(connectionString);
+
+ // Determine if an endpoint is localhost/loopback
+ static bool IsLocalhostEndpoint(EndPoint ep) => ep switch
+ {
+ DnsEndPoint dns => string.Equals(dns.Host, "localhost", StringComparison.OrdinalIgnoreCase),
+ IPEndPoint ip => IPAddress.IsLoopback(ip.Address),
+ _ => false,
+ };
+
+ // If no password is provided, and the endpoint (or at least one of them) is non-localhost,
+ // attempt to use Entra authentication.
+ if (string.IsNullOrEmpty(options.Password) && !options.EndPoints.Any(IsLocalhostEndpoint))
+ {
+ options = await options.ConfigureForAzureWithTokenCredentialAsync(new DefaultAzureCredential());
+ }
+
+ return await ConnectionMultiplexer.ConnectAsync(options);
+ }
+
///
/// Configure GraphQL services within the service collection of the
/// request pipeline.