feat(deploy): automate Entra ID authentication configuration and sample bundle processing#565
Open
Dongbumlee wants to merge 7 commits intomainfrom
Open
feat(deploy): automate Entra ID authentication configuration and sample bundle processing#565Dongbumlee wants to merge 7 commits intomainfrom
Dongbumlee wants to merge 7 commits intomainfrom
Conversation
Adds infra/scripts/configure_auth.{sh,ps1} invoked at the end of the
azd postprovision hook so 'azd up' produces a fully authenticated
deployment without the manual steps in docs/ConfigureAppAuthentication.md.
Idempotent (reuses app regs persisted in azd env by appId, reuses
existing container app secrets) and skippable via AZURE_SKIP_AUTH_SETUP.
Covers:
- Web + API app registrations with redirect URIs, exposed scopes,
Graph User.Read, ID/access token issuance
- Best-effort admin consent with clear manual-action message on failure
- Container App EasyAuth Microsoft provider on both apps
- API authConfig allowedApplications = Web client id
- Web container env vars APP_WEB_CLIENT_ID / APP_WEB_SCOPE / APP_API_SCOPE
- Final lockdown: Web -> RedirectToLoginPage, API -> Return401
…ze issuer Three fixes discovered during end-to-end azd up testing: 1. `az containerapp auth microsoft update` rejects `--issuer` and `--tenant-id` together; the issuer is derived from tenant-id. 2. `azd env get-value AZURE_TENANT_ID` prints its error message to stdout (not stderr), corrupting TENANT_ID when that key is absent. Read from `az account show` first instead. 3. `--allowed-token-audiences api://<clientId>` breaks EasyAuth login because the ID tokens it issues have `aud=<clientId>` (GUID), not the identifierUri. Drop the override and normalize `allowedAudiences` to just the clientId via an authConfig PUT (which also clears stale values left by prior runs and fixes `openIdIssuer` if it was previously corrupted). Verified: Web `/.auth/login/aad` -> 302 to login.microsoftonline.com with the correct client_id, redirect_uri, and scopes; API returns 401 to unauthenticated callers; allowedApplications on the API restricts callers to the Web clientId.
Default app registrations have requestedAccessTokenVersion=null, which means Entra issues v1 access tokens with aud='api://<clientId>'. EasyAuth was configured with allowedAudiences=['<clientId>'] (bare GUID only), so every Web->API call failed audience validation and returned 401. Include both forms so the script works regardless of the app reg's accessTokenAcceptedVersion setting.
- DeploymentGuide.md §5.2 rewritten: describes the automatic flow, permission requirements, admin-consent failure handling, and the AZURE_SKIP_AUTH_SETUP escape hatch. - ConfigureAppAuthentication.md gets a banner making clear the manual steps are now a fallback (for tenants that block programmatic app registration or admin consent).
- Add bundle_info.json manifests for claim_date_of_loss and claim_hail - Add Step 4 to post_deployment.ps1 and post_deployment.sh - Creates claim batch with schemaset ID - Uploads files with mapped schema IDs - Submits batch for workflow processing - Update DeploymentGuide.md with new step and sample output - Update AVMPostDeploymentGuide.md with manual sample processing instructions - Normalize output prefixes: ASCII dashes for ps1, emojis for sh
configure_auth.sh / configure_auth.ps1:
- Set globalValidation (requireAuthentication, unauthenticatedClientAction,
redirectToProvider) directly in the authConfig PUT — the CLI flags were not
reliably populating redirectToProvider, leaving the Web app responding 401
to browser users instead of redirecting to AAD.
- Explicitly POST oauth2PermissionGrants to grant the API user_impersonation
scope to the Web service principal. 'az ad app permission admin-consent'
silently consents Microsoft Graph only and skips custom-API delegated
scopes, which made MSAL acquireTokenSilent fail and rendered a blank SPA
after successful login.
- Override APP_WEB_AUTHORITY env var on the Web container app so MSAL.js
uses a properly-formed authority URL.
- Restart Web + API container revisions after secrets/env updates so the
new values take effect without a manual restart.
infra/main.bicep:
- Drop redundant slash in APP_WEB_AUTHORITY composition; loginEndpoint
already has a trailing slash, so '${loginEndpoint}/${tenantId}' produced
a double-slash URL that broke MSAL.
infra/scripts/post_deployment.sh:
- Fix bash array iteration in Step 4b schema-id lookup. The previous
'for RID in $REGISTERED_IDS' de-references the array as a scalar (only
the first element), causing only one file per sample bundle to upload.
Switched to indexed iteration with ${!REGISTERED_IDS[@]} and a name
lookup against REGISTERED_NAMES[$i].
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
docs/DeploymentGuide.md§5.2. Afterazd up, both Web and API container apps are registered, granted admin consent, configured for EasyAuth, and wired up — no portal clicks required.claim_date_of_loss,claim_hail) end-to-end after schema/schemaset registration so first-time users see results immediately.docs/DeploymentGuide.mdto reflect the new automated flow, with a manual fallback link kept for environments where the automation can't run.The new automation is implemented in
infra/scripts/configure_auth.sh/configure_auth.ps1and invoked frompost_deployment.sh/post_deployment.ps1. It is idempotent and safe to re-run.Does this introduce a breaking change?
Golden Path Validation
Validated 5 full
azd updeployments (deploytest-wslthroughdeploytest-wsl5) against a clean subscription. On the final cycle:Deployment Validation
Validated against both the standard profile and reviewed for compatibility with the AVM-based WAF profile (
main.waf.parameters.json); ingress remains external on the Container Apps so the auth-config script's HTTPS calls work in both profiles. A note covering this has been added to the deployment guide.What to Check
Verify that the following are valid
infra/scripts/configure_auth.shand.ps1are functionally equivalent.post_deployment.shStep 4 schema-id lookup correctly maps every file in a bundle to its schema (the previous bash array iteration only matched the first element).infra/main.bicepAPP_WEB_AUTHORITYno longer produces a double-slash URL (environment().authentication.loginEndpointalready includes a trailing slash).docs/DeploymentGuide.md§5 reflects the automated flow; the manualdocs/ConfigureAppAuthentication.mdis preserved as a fallback.Other Information
Bugs discovered and fixed during e2e validation:
globalValidation.redirectToProvideris not reliably populated by theaz containerapp authCLI flags — it must be set directly in theauthConfigPUT, otherwise unauthenticated browser users get a 401 instead of being redirected to AAD.az ad app permission admin-consentsilently consents Microsoft Graph only and skips custom-API delegated scopes. The Web SP needs an explicitoauth2PermissionGrantsPOST foruser_impersonationon the API app, or MSALacquireTokenSilentfails after sign-in and the SPA renders blank.az containerapp secret setdoes not trigger a new revision; the script now restarts the active Web + API revisions to apply changes.APP_WEB_AUTHORITYinmain.bicephad a redundant/betweenloginEndpointandtenantId, breaking MSAL.js.for x in $ARRinstead of${ARR[@]}) caused only the first file in each sample bundle to upload; fixed with indexed iteration. (PowerShell path was already correct via hashtable lookup.)