Skip to main content
emnode
Compliance Medium severity MCSB DP-3

Microsoft Defender for Cloud · Azure App Service

API App should only be accessible over HTTPS

Written and reviewed by Emnode · Last reviewed

What does the recommendation "API App should only be accessible over HTTPS" check?

Flags any App Service app of kind 'api' whose 'properties.httpsOnly' setting is false, meaning the app still answers plain HTTP and does not redirect callers to TLS. It evaluates only the app-level HTTPS-only toggle: it does not check the minimum TLS version, certificate binding, custom-domain bindings, or whether your own code enforces HSTS, so an app can pass this check while still negotiating outdated TLS 1.0. Note that the original API-App-specific policy behind this recommendation is deprecated; Microsoft now folds API apps into the broader 'App Service apps should only be accessible over HTTPS' definition, which evaluates the same httpsOnly property.

Why does "API App should only be accessible over HTTPS" matter?

When httpsOnly is off, App Service keeps the HTTP listener open alongside HTTPS, so any client, link or integration can reach the API in clear text. Tokens, API keys and payloads then travel unencrypted, where they can be read or altered by anyone positioned on the network path, from a coffee-shop Wi-Fi router to a compromised upstream proxy. For an API tier this is acute: the credentials it carries usually unlock downstream systems, so one intercepted bearer token can be replayed to pull data or move laterally. Enforcing HTTPS-only closes the plaintext door and pushes every caller onto an encrypted, authenticated channel, which is also a baseline expectation in most data-protection and PCI audits.

How do I fix "API App should only be accessible over HTTPS"?

  1. Turn on HTTPS-only on the app: in the portal open the API app, go to Settings then Configuration (or the TLS/SSL settings blade) and switch 'HTTPS Only' to On, or run 'az webapp update --resource-group <rg> --name <app> --set httpsOnly=true' (the '--https-only true' shorthand also works). Confirm with 'az webapp show --resource-group <rg> --name <app> --query httpsOnly'.
  2. Set the floor in code so new deployments are safe by default: in Bicep add 'httpsOnly: true' under the Microsoft.Web/sites resource properties, and while you are there set 'siteConfig.minTlsVersion: '1.2'' since httpsOnly alone does not raise the TLS floor.
  3. Enforce it across the estate with policy. Look the definition up by display name rather than pasting a GUID: pid=$(az policy definition list --query "[?displayName=='App Service apps should only be accessible over HTTPS'].name" -o tsv); az policy assignment create --name app-https-only --policy "$pid" --scope /subscriptions/<sub-id>. Use this current definition rather than the deprecated API-App-only one.

Remediation script · bash

# Close the highest-impact plaintext doors first: the Redis non-SSL port,
# then HTTPS-only + a modern TLS floor on every web app.

# Redis: disable the non-SSL port 6379 and require TLS 1.2 (clients use 6380).
for cache in $(az redis list --query "[?enableNonSslPort].name" -o tsv); do
  rg=$(az redis list --query "[?name=='$cache'].resourceGroup" -o tsv)
  az redis update --name "$cache" --resource-group "$rg" \
    --set enableNonSslPort=false minimumTlsVersion=1.2
  echo "$cache: non-SSL port disabled, min TLS 1.2"
done

# Web apps: enforce HTTPS only and raise the TLS floor.
for app in $(az webapp list --query "[?httpsOnly==\`false\`].name" -o tsv); do
  rg=$(az webapp list --query "[?name=='$app'].resourceGroup" -o tsv)
  az webapp update --name "$app" --resource-group "$rg" --https-only true
  az webapp config set --name "$app" --resource-group "$rg" --min-tls-version 1.2
  echo "$app: HTTPS only, min TLS 1.2"
done

# Functions follow the same pattern with az functionapp update --set httpsOnly=true.

# Ratchet it shut: assign the built-in deny policy for web apps over HTTPS only.
az policy assignment create \
  --name require-https-webapp \
  --policy a4af4a39-4135-47fb-b175-47fbdf85311d \
  --scope "/subscriptions/00000000-0000-0000-0000-000000000000"

Full walkthrough (console steps, edge cases and verification) in the lesson Enforce encryption in transit across Azure services.

Is "API App should only be accessible over HTTPS" a false positive?

An internal API reached only through Azure Front Door or Application Gateway where TLS terminates at the edge and the backend pool already forces HTTPS can still flag, because the check reads the app's own httpsOnly property, not the gateway in front of it. The correct fix is still to set httpsOnly=true on the app itself so the origin cannot be reached over plain HTTP if someone discovers its default azurewebsites.net hostname and bypasses the front door.