Skip to content

[Bug]: setup-entra-app.ps1 uses appRole GUIDs as delegated scopes — admin consent fails for all fresh deployments #52

Description

Summary

setup-entra-app.ps1 declares three Microsoft Graph / Log Analytics permission GUIDs that are not valid delegated (Scope) permissions. Because Entra validates a consent request atomically, admin consent fails for the entire app, and no service principal is created. Any fresh azd up into a tenant that requires admin consent is blocked at the "Connect Azure" step.

Affected code

src/Dashboard/setup-entra-app.ps1 (lines 138, 141, 145 — used as type = "Scope" on lines 163, 166, 172):

$graphOrgReadAll   = "498476ce-e0fe-48b0-b801-37ba7e2685c6"   # Organization.Read.All
$graphGroupReadAll = "5b567255-7703-4780-807c-7be8301ae99b"   # Group.Read.All
$laDataRead        = "e4aa47b9-9a69-4109-82ed-36ec70d85f3f"   # Data.Read

Root cause

Two of the GUIDs are application role IDs (app-only permissions), not delegated scopes, yet they are declared as type = "Scope". The third does not exist on the Log Analytics API at all.

Variable Current value What it actually is
$graphOrgReadAll 498476ce-... Organization.Read.All appRole (app-only)
$graphGroupReadAll 5b567255-... Group.Read.All appRole (app-only)
$laDataRead e4aa47b9-... not present in Log Analytics oauth2PermissionScopes

The script's own output text (lines 190–194) states these are intended to be delegated:

Log Analytics: Data.Read (delegated, read-only)
Microsoft Graph: ... (all delegated, read-only)

So the intent is delegated scopes; the values were taken from the appRole column.

Reproduction

  1. azd up into a tenant where "Users can register applications" / user consent is restricted.
  2. Sign in, click Connect Azure.
  3. Entra shows "Need admin approval".
  4. A Global/Application Administrator grants consent — it silently fails.
  5. az ad sp show --id <appId>Resource does not exist (no service principal was ever created).

Verification

# Log Analytics API publishes exactly one delegated scope, and it is not e4aa47b9-...
az ad sp show --id ca7f3f0b-7d91-482c-8e09-c5d840d0eac5 `
  --query "oauth2PermissionScopes[].{id:id,value:value}" -o json
# => [ { "id": "e8dac03d-d467-4a7e-9293-9cca7df08b31", "value": "Data.Read" } ]

# The two Graph GUIDs resolve as appRoles, not oauth2PermissionScopes
az ad sp show --id 00000003-0000-0000-c000-000000000000 `
  --query "appRoles[?id=='498476ce-e0fe-48b0-b801-37ba7e2685c6'].value" -o tsv
# => Organization.Read.All

These are Microsoft first-party service principals, so the IDs are identical in every tenant — this is not environment-specific.

Proposed fix

-$graphOrgReadAll = "498476ce-e0fe-48b0-b801-37ba7e2685c6"         # Organization.Read.All
+$graphOrgReadAll = "4908d5b9-3fb2-4b1e-9336-1888b7937185"         # Organization.Read.All

-$graphGroupReadAll = "5b567255-7703-4780-807c-7be8301ae99b"       # Group.Read.All
+$graphGroupReadAll = "5f8c59db-677d-491f-a6b8-5f174b11ec1d"       # Group.Read.All

-$laDataRead = "e4aa47b9-9a69-4109-82ed-36ec70d85f3f"              # Data.Read
+$laDataRead = "e8dac03d-d467-4a7e-9293-9cca7df08b31"              # Data.Read

After applying this, every requested ID resolves against its resource's published oauth2PermissionScopes, and admin consent succeeds.

Secondary issue: silent failure of the redirect-URI patch

infra/scripts/postprovision.ps1 (line 40) patches the production redirect URI:

az ad app update --id $objectId --web-redirect-uris @merged --output none

In my run this left only http://localhost:5000/auth/microsoft/callback on the app registration — the https://<webHost>/auth/microsoft/callback entry was never added, which would have produced AADSTS50011 after consent. The script's fallback branch (line 45) prints a warning, but it scrolls past in normal azd up output.

Suggestion: fail loudly (non-zero exit) when the redirect-URI patch does not apply, or re-read and assert the URIs afterwards.

Suggested hardening

Rather than hardcoding GUIDs, resolve them at runtime so this class of bug cannot recur:

$laDataRead = az ad sp show --id $laAppId `
  --query "oauth2PermissionScopes[?value=='Data.Read'].id" -o tsv

Environment

  • azd 1.25.6
  • Azure CLI 2.83.0
  • PowerShell 7.5.8 / Windows 11
  • Repo main as of commit 758c2c9

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions