Back to blog
AzureBest PracticesCloud SecurityCompute & ContainersIdentity & Access

Azure Container App Authentication Not Enabled: Why It Matters and How to Fix It

Learn why Azure Container Apps without built-in authentication are a security risk, and get step-by-step CLI, Bicep, and policy-as-code fixes.

TL;DR

This check flags Azure Container Apps that have no built-in authentication, meaning anyone who can reach the app's URL can hit it directly. Turn on the Container Apps auth feature (Easy Auth) with an identity provider so unauthenticated traffic gets rejected before it reaches your code.

Azure Container Apps gives you a fast way to run containerized workloads without managing the underlying Kubernetes plumbing. That convenience comes with a default that catches a lot of teams off guard: a Container App with an external ingress is reachable on the public internet, and unless you wire up authentication yourself, it serves every request that lands on its endpoint.

The containerapps_noauth check looks for Container Apps that do not have the built-in authentication feature enabled. If you are relying on your application code, an API gateway, or "nobody knows the URL" to keep things private, this check is telling you that the platform itself is doing nothing to verify who is calling.


What this check detects

Azure Container Apps includes a managed authentication and authorization layer, often called Easy Auth, the same feature available in Azure App Service. When enabled, it runs as a sidecar in front of your container and handles the OpenID Connect or OAuth flow before any request reaches your application process.

The check inspects the authConfig resource attached to each Container App. It fails when:

  • No authConfig exists for the app, or
  • Authentication exists but the global enabled flag is set to false, or
  • The app has external ingress and no identity provider is configured to gate access.

Note: Built-in authentication is separate from network controls. You can have an app behind a private VNet and still want authentication, and you can have a public app that genuinely should be anonymous. This check focuses on whether the platform-level auth layer is configured, not whether every app must have it.


Why it matters

An external Container App ingress resolves to a public hostname like myapp.calmwater-12345.eastus.azurecontainerapps.io. These hostnames are not secret. They show up in DNS logs, TLS certificate transparency feeds, browser history, and the Azure portal. Treating the URL as a secret is security through obscurity, and it fails the moment anyone shares a link or a scanner sweeps the address space.

Here is what tends to go wrong when authentication is missing:

  • Internal tools exposed by accident. A dashboard, admin panel, or debug endpoint gets deployed with external ingress for "quick testing" and stays that way. Now anyone can read it.
  • Unprotected APIs. A backend API meant to be called only by an authenticated frontend ends up accepting requests from anyone, letting attackers enumerate endpoints and pull data.
  • Resource abuse. Open endpoints get hammered by bots, driving up your scaling costs and creating noise that hides real attacks.
  • Pivot points. An exposed app with environment variables, managed identity tokens, or access to internal services becomes a foothold into the rest of your environment.

The risk is sharper than with a traditional VM because Container Apps often hold managed identity credentials that can reach storage accounts, Key Vault, or databases. If the front door is open and the app proxies those identities, an attacker does not need to crack anything.

Danger: An unauthenticated Container App that uses a managed identity is effectively handing its Azure permissions to the public internet. Anyone who can trigger a code path that uses that identity can act with its access rights. Audit these apps first.


How to fix it

You enable authentication by creating an authConfig on the Container App and pointing it at an identity provider. Microsoft Entra ID is the most common choice for internal apps, but you can also use Google, GitHub, Facebook, or any OpenID Connect provider.

Step 1: Register an app in Microsoft Entra ID

First create an app registration so Container Apps has an identity to authenticate against.

# Create the Entra ID app registration
az ad app create \
  --display-name "my-containerapp-auth" \
  --web-redirect-uris "https://myapp.calmwater-12345.eastus.azurecontainerapps.io/.auth/login/aad/callback"

# Note the appId returned, you will need it below

Step 2: Enable authentication on the Container App

Use the az containerapp auth commands to turn on Entra ID authentication and require a logged-in user for every request.

# Configure Microsoft Entra ID as the provider
az containerapp auth microsoft update \
  --name my-containerapp \
  --resource-group my-rg \
  --client-id "" \
  --issuer "https://login.microsoftonline.com//v2.0" \
  --tenant-id ""

# Require authentication and reject anonymous requests
az containerapp auth update \
  --name my-containerapp \
  --resource-group my-rg \
  --unauthenticated-client-action Return401 \
  --enabled true

Note: The --unauthenticated-client-action setting controls what happens to anonymous traffic. Return401 is right for APIs, since it sends a clean unauthorized response. RedirectToLoginPage suits browser-facing apps because it bounces users to the sign-in flow.

Step 3: Verify it works

# An anonymous request should now be rejected
curl -i https://myapp.calmwater-12345.eastus.azurecontainerapps.io/

# Expect: HTTP/1.1 401 Unauthorized (for Return401)
# or a 302 redirect to the login page

Infrastructure as Code: Bicep

If you manage Container Apps with Bicep, define the authConfig as a child resource so authentication is part of the deployment instead of a manual afterthought.

resource authConfig 'Microsoft.App/containerApps/authConfigs@2024-03-01' = {
  parent: containerApp
  name: 'current'
  properties: {
    platform: {
      enabled: true
    }
    globalValidation: {
      unauthenticatedClientAction: 'Return401'
      redirectToProvider: 'azureactivedirectory'
    }
    identityProviders: {
      azureActiveDirectory: {
        enabled: true
        registration: {
          clientId: entraAppClientId
          openIdIssuer: 'https://login.microsoftonline.com/${tenantId}/v2.0'
        }
      }
    }
  }
}

Warning: Enabling authentication on a live app will immediately start rejecting unauthenticated traffic. If clients call this app without tokens today, coordinate the rollout. Update callers to send valid tokens first, or stage the change in a non-production environment to avoid breaking integrations.


How to prevent it from happening again

Fixing one app is fine. Stopping the next twenty from shipping the same way is what actually moves the needle. Bake the control into the path that creates resources.

Azure Policy

Use Azure Policy to audit or deny Container Apps that lack an auth config. A deny effect blocks non-compliant deployments at the control plane, before the app ever runs.

{
  "policyRule": {
    "if": {
      "allOf": [
        {
          "field": "type",
          "equals": "Microsoft.App/containerApps"
        },
        {
          "field": "Microsoft.App/containerApps/configuration.ingress.external",
          "equals": "true"
        }
      ]
    },
    "then": {
      "effect": "audit"
    }
  }
}

Start with audit to measure how many apps are affected, then tighten to deny once teams have remediated and understand the requirement.

CI/CD gates

If you deploy through pipelines, scan your IaC for missing authConfig blocks before anything reaches Azure. A simple check in your pipeline can fail the build when an externally exposed Container App has no auth defined.

# Example: fail if a Bicep file declares external ingress without an authConfig
if grep -q "external: true" main.bicep && ! grep -q "authConfigs" main.bicep; then
  echo "External Container App found without authConfig. Failing build."
  exit 1
fi

Tip: Lensix runs the containerapps_noauth check continuously across your subscriptions, so you catch drift even when someone changes a setting in the portal outside your pipeline. Pair the policy-as-code gate at deploy time with continuous scanning at runtime to close both gaps.


Best practices

  • Default to internal ingress. If an app only needs to talk to other services in your environment, set ingress to internal so it never gets a public hostname in the first place.
  • Layer your controls. Built-in authentication answers "who are you," not "what are you allowed to do." Combine it with token validation and authorization checks in your application for sensitive operations.
  • Use Entra ID for internal apps. It gives you conditional access, MFA, and centralized revocation without writing custom login flows.
  • Validate tokens at the app too. Easy Auth passes claims to your container in headers. Read and verify them rather than trusting that the request reached you at all.
  • Scope managed identities tightly. If an exposed app does get compromised, least-privilege identity assignments limit how far an attacker can move.
  • Review external apps on a schedule. Inventory every Container App with external ingress and confirm each one is intentionally public. Anonymous access should be a deliberate decision, not a default.

Authentication on a Container App is one of those settings that costs a few minutes to enable and saves you from a class of incidents that are entirely preventable. Treat an open endpoint as a finding to justify, not a state to accept.