Skip to content

Azure Cache for Redis Integration (Microsoft Entra Authentication)

Use this recipe to connect Azure Container Apps to Azure Cache for Redis with Microsoft Entra authentication first and access keys only as a fallback.

Architecture

flowchart TD
    C[Client] --> I[Container Apps Ingress]
    I --> APP[Java Container App]
    APP --> REDIS[Azure Cache for Redis]
    APP -.-> MI[Managed Identity]
    MI -.-> ENTRA[Microsoft Entra ID]
    MI -.-> REDIS

Solid arrows show runtime data flow. Dashed arrows show identity and authentication.

Prerequisites

  • Existing Container App: $APP_NAME in $RG
  • Existing Azure Cache for Redis instance with Microsoft Entra authentication enabled
  • TLS access enabled on port 6380

Step 1: Enable managed identity on the Container App

az containerapp identity assign \
  --name "$APP_NAME" \
  --resource-group "$RG" \
  --system-assigned

export PRINCIPAL_ID=$(az containerapp show \
  --name "$APP_NAME" \
  --resource-group "$RG" \
  --query "identity.principalId" \
  --output tsv)

Step 2: Assign Redis data access

az redis access-policy-assignment create \
  --name "$REDIS_NAME" \
  --resource-group "$RG" \
  --access-policy-name "Data Owner" \
  --object-id "$PRINCIPAL_ID" \
  --object-id-alias "$APP_NAME"

Step 3: Configure non-secret Redis settings

az containerapp update \
  --name "$APP_NAME" \
  --resource-group "$RG" \
  --set-env-vars REDIS_HOST="$REDIS_NAME.redis.cache.windows.net" REDIS_PORT="6380" REDIS_USERNAME="$PRINCIPAL_ID"

Step 4: Java code (Microsoft Entra token authentication)

Add dependencies:

<dependency>
  <groupId>com.azure</groupId>
  <artifactId>azure-identity</artifactId>
</dependency>
<dependency>
  <groupId>io.lettuce</groupId>
  <artifactId>lettuce-core</artifactId>
</dependency>

Use DefaultAzureCredential to fetch the Redis access token:

import com.azure.core.credential.AccessToken;
import com.azure.core.credential.TokenRequestContext;
import com.azure.identity.DefaultAzureCredentialBuilder;
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisURI;
import io.lettuce.core.api.StatefulRedisConnection;

public class RedisRecipe {
    public static void main(String[] args) {
        String host = System.getenv("REDIS_HOST");
        int port = Integer.parseInt(System.getenv().getOrDefault("REDIS_PORT", "6380"));

        String password = System.getenv("REDIS_ACCESS_KEY");
        if (password == null || password.isBlank()) {
            AccessToken token = new DefaultAzureCredentialBuilder()
                .build()
                .getToken(new TokenRequestContext().addScopes("https://redis.azure.com/.default"))
                .block();
            password = token.getToken();
        }

        RedisURI redisUri = RedisURI.builder()
            .withHost(host)
            .withPort(port)
            .withSsl(true)
            .withAuthentication(System.getenv("REDIS_USERNAME"), password)
            .build();

        try (RedisClient client = RedisClient.create(redisUri);
             StatefulRedisConnection<String, String> connection = client.connect()) {
            connection.sync().setex("health", 60, "ok");
            System.out.println(connection.sync().get("health"));
        }
    }
}

Warning

The Entra token used for Redis expires. For long-lived connections, implement token refresh and reconnect logic that matches the guidance for your Redis tier and client library.

Step 5: Access key fallback

az containerapp secret set \
  --name "$APP_NAME" \
  --resource-group "$RG" \
  --secrets redis-access-key="<redis-primary-key>"

az containerapp update \
  --name "$APP_NAME" \
  --resource-group "$RG" \
  --set-env-vars REDIS_HOST="$REDIS_NAME.redis.cache.windows.net" REDIS_PORT="6380" REDIS_ACCESS_KEY=secretref:redis-access-key REDIS_USERNAME="default"

Verification

  1. Confirm the access policy assignment exists.
  2. Confirm application logs show successful Redis SETEX and GET operations.
  3. Confirm clients are using TLS on port 6380.

See Also

Sources