Skip to content

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

Description

@Brodefist

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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions