From 932d1e0ddac032d4b3272445b8c894dde38e4265 Mon Sep 17 00:00:00 2001 From: Slawomir Koszewski Date: Sat, 7 Feb 2026 13:21:09 +0100 Subject: [PATCH] Fix PowerShell app update flow --- scripts/New-PublicClientApplication.ps1 | 63 +++++++++++++++-------- scripts/create-pca.sh | 67 +++++++++++++++++-------- 2 files changed, 88 insertions(+), 42 deletions(-) diff --git a/scripts/New-PublicClientApplication.ps1 b/scripts/New-PublicClientApplication.ps1 index 8b7660f..6fd2dd7 100644 --- a/scripts/New-PublicClientApplication.ps1 +++ b/scripts/New-PublicClientApplication.ps1 @@ -92,15 +92,20 @@ $existingAppId = az ad app list --display-name $AppName --query "[0].appId" -o t if ($LASTEXITCODE -ne 0) { throw "Failed to query existing applications." } -if (-not [string]::IsNullOrWhiteSpace($existingAppId)) { - Write-Error "Application '$AppName' already exists." - exit 1 -} -# Create the app -$appId = az ad app create --display-name $AppName --query "appId" -o tsv -if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($appId)) { - throw "Failed to create application '$AppName'." +if (-not [string]::IsNullOrWhiteSpace($existingAppId)) { + $confirmation = Read-Host "Application '$AppName' already exists. Update it? [y/N]" + if ($confirmation -notmatch '^(?i:y|yes)$') { + Write-Host "Canceled." + exit 0 + } + $appId = $existingAppId +} else { + # Create the app + $appId = az ad app create --display-name $AppName --query "appId" -o tsv + if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($appId)) { + throw "Failed to create application '$AppName'." + } } $requiredResourceAccess = Get-RequiredResourceAccess ` @@ -110,26 +115,24 @@ $requiredResourceAccess = Get-RequiredResourceAccess ` -AzureDevOpsScopeId $azureDevOpsScopeId ` -AzureServiceMgmtAppId $azureServiceMgmtAppId ` -AzureServiceMgmtScopeId $azureServiceMgmtScopeId | ConvertTo-Json -Depth 10 -Compress - -$publicClientRedirectUris = @( - "http://localhost", - "msal${appId}://auth" -) | ConvertTo-Json -Compress +$requiredResourceAccessFile = [System.IO.Path]::GetTempFileName() +Set-Content -Path $requiredResourceAccessFile -Value $requiredResourceAccess -NoNewline # Configure app to match "Azure Node Playground Public". az ad app update ` --id $appId ` - --set ` - "signInAudience=AzureADMyOrg" ` - "isFallbackPublicClient=true" ` - "requiredResourceAccess=$requiredResourceAccess" ` - "publicClient.redirectUris=$publicClientRedirectUris" ` - "web.implicitGrantSettings.enableAccessTokenIssuance=true" ` - "web.implicitGrantSettings.enableIdTokenIssuance=true" | Out-Null + --sign-in-audience AzureADMyOrg ` + --is-fallback-public-client true ` + --required-resource-accesses "@$requiredResourceAccessFile" ` + --public-client-redirect-uris "http://localhost" "msal${appId}://auth" ` + --enable-access-token-issuance true ` + --enable-id-token-issuance true | Out-Null if ($LASTEXITCODE -ne 0) { + Remove-Item -Path $requiredResourceAccessFile -Force -ErrorAction SilentlyContinue throw "Failed to configure application '$AppName'." } +Remove-Item -Path $requiredResourceAccessFile -Force -ErrorAction SilentlyContinue # Azure CLI is used to grant admin consent. @@ -145,5 +148,23 @@ if ($LASTEXITCODE -ne 0) { throw "Failed to grant admin consent for '$AppName' ($appId)." } -Write-Host "Created application '$AppName'" +$tenantId = az account show --query tenantId -o tsv +if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($tenantId)) { + throw "Failed to resolve tenantId from current Azure CLI context." +} + +if ([string]::IsNullOrWhiteSpace($existingAppId)) { + Write-Host "Created application '$AppName'" +} else { + Write-Host "Updated application '$AppName'" +} Write-Host "appId: $appId" + +$configTemplate = @" +export const config = { + "appName": "$AppName", + "tenantId": "$tenantId", + "clientId": "$appId" +}; +"@ +Write-Output $configTemplate diff --git a/scripts/create-pca.sh b/scripts/create-pca.sh index 1e83b05..7ea9df4 100755 --- a/scripts/create-pca.sh +++ b/scripts/create-pca.sh @@ -42,15 +42,21 @@ function main() { # Find the app by name APP_ID=$(az ad app list --display-name "$APP_NAME" --query "[0].appId" -o tsv) if [[ -n "$APP_ID" ]]; then - echo "Error: Application '$APP_NAME' already exists." - exit 1 + local USER_CONFIRMATION + read -r -p "Application '$APP_NAME' already exists. Update it? [y/N]: " USER_CONFIRMATION + if [[ ! "$USER_CONFIRMATION" =~ ^([yY][eE][sS]|[yY])$ ]]; then + echo "Canceled." + exit 0 + fi fi - # Create the app - APP_ID=$(az ad app create --display-name "$APP_NAME" --query "appId" -o tsv) + # Create the app when it does not already exist. if [[ -z "$APP_ID" ]]; then - echo "Error: Failed to create application '$APP_NAME'." - exit 1 + APP_ID=$(az ad app create --display-name "$APP_NAME" --query "appId" -o tsv) + if [[ -z "$APP_ID" ]]; then + echo "Error: Failed to create application '$APP_NAME'." + exit 1 + fi fi local M365_GRAPH_APP_ID="00000003-0000-0000-c000-000000000000" @@ -94,25 +100,26 @@ function main() { EOF ) - local PUBLIC_CLIENT_REDIRECT_URIS_JSON - PUBLIC_CLIENT_REDIRECT_URIS_JSON=$(cat < "$REQUIRED_RESOURCE_ACCESS_FILE" # Configure app to match "Azure Node Playground Public". az ad app update \ --id "$APP_ID" \ - --set signInAudience=AzureADMyOrg \ - isFallbackPublicClient=true \ - requiredResourceAccess="$REQUIRED_RESOURCE_ACCESS_JSON" \ - publicClient.redirectUris="$PUBLIC_CLIENT_REDIRECT_URIS_JSON" \ - web.implicitGrantSettings.enableAccessTokenIssuance=true \ - web.implicitGrantSettings.enableIdTokenIssuance=true \ + --sign-in-audience AzureADMyOrg \ + --is-fallback-public-client true \ + --required-resource-accesses @"$REQUIRED_RESOURCE_ACCESS_FILE" \ + --public-client-redirect-uris "http://localhost" "msal${APP_ID}://auth" \ + --enable-access-token-issuance true \ + --enable-id-token-issuance true \ 1>/dev/null + local UPDATE_EXIT_CODE=$? + rm -f "$REQUIRED_RESOURCE_ACCESS_FILE" + if [[ $UPDATE_EXIT_CODE -ne 0 ]]; then + echo "Error: Failed to configure application '$APP_NAME' ($APP_ID)." + exit 1 + fi # Ensure service principal exists before granting tenant-wide admin consent. az ad sp create --id "$APP_ID" 1>/dev/null 2>/dev/null || true @@ -124,8 +131,26 @@ EOF exit 1 fi - echo "Created application '$APP_NAME'" + local TENANT_ID + TENANT_ID=$(az account show --query tenantId -o tsv) + if [[ -z "$TENANT_ID" ]]; then + echo "Error: Failed to resolve tenantId from current Azure CLI context." + exit 1 + fi + + if [[ -z "$USER_CONFIRMATION" ]]; then + echo "Created application '$APP_NAME'" + else + echo "Updated application '$APP_NAME'" + fi echo "appId: $APP_ID" + cat <