Fix PowerShell app update flow

This commit is contained in:
2026-02-07 13:21:09 +01:00
parent c2820c0320
commit 932d1e0dda
2 changed files with 88 additions and 42 deletions

View File

@@ -92,15 +92,20 @@ $existingAppId = az ad app list --display-name $AppName --query "[0].appId" -o t
if ($LASTEXITCODE -ne 0) { if ($LASTEXITCODE -ne 0) {
throw "Failed to query existing applications." throw "Failed to query existing applications."
} }
if (-not [string]::IsNullOrWhiteSpace($existingAppId)) {
Write-Error "Application '$AppName' already exists."
exit 1
}
# Create the app if (-not [string]::IsNullOrWhiteSpace($existingAppId)) {
$appId = az ad app create --display-name $AppName --query "appId" -o tsv $confirmation = Read-Host "Application '$AppName' already exists. Update it? [y/N]"
if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($appId)) { if ($confirmation -notmatch '^(?i:y|yes)$') {
throw "Failed to create application '$AppName'." 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 ` $requiredResourceAccess = Get-RequiredResourceAccess `
@@ -110,26 +115,24 @@ $requiredResourceAccess = Get-RequiredResourceAccess `
-AzureDevOpsScopeId $azureDevOpsScopeId ` -AzureDevOpsScopeId $azureDevOpsScopeId `
-AzureServiceMgmtAppId $azureServiceMgmtAppId ` -AzureServiceMgmtAppId $azureServiceMgmtAppId `
-AzureServiceMgmtScopeId $azureServiceMgmtScopeId | ConvertTo-Json -Depth 10 -Compress -AzureServiceMgmtScopeId $azureServiceMgmtScopeId | ConvertTo-Json -Depth 10 -Compress
$requiredResourceAccessFile = [System.IO.Path]::GetTempFileName()
$publicClientRedirectUris = @( Set-Content -Path $requiredResourceAccessFile -Value $requiredResourceAccess -NoNewline
"http://localhost",
"msal${appId}://auth"
) | ConvertTo-Json -Compress
# Configure app to match "Azure Node Playground Public". # Configure app to match "Azure Node Playground Public".
az ad app update ` az ad app update `
--id $appId ` --id $appId `
--set ` --sign-in-audience AzureADMyOrg `
"signInAudience=AzureADMyOrg" ` --is-fallback-public-client true `
"isFallbackPublicClient=true" ` --required-resource-accesses "@$requiredResourceAccessFile" `
"requiredResourceAccess=$requiredResourceAccess" ` --public-client-redirect-uris "http://localhost" "msal${appId}://auth" `
"publicClient.redirectUris=$publicClientRedirectUris" ` --enable-access-token-issuance true `
"web.implicitGrantSettings.enableAccessTokenIssuance=true" ` --enable-id-token-issuance true | Out-Null
"web.implicitGrantSettings.enableIdTokenIssuance=true" | Out-Null
if ($LASTEXITCODE -ne 0) { if ($LASTEXITCODE -ne 0) {
Remove-Item -Path $requiredResourceAccessFile -Force -ErrorAction SilentlyContinue
throw "Failed to configure application '$AppName'." throw "Failed to configure application '$AppName'."
} }
Remove-Item -Path $requiredResourceAccessFile -Force -ErrorAction SilentlyContinue
# Azure CLI is used to grant admin consent. # 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)." 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" Write-Host "appId: $appId"
$configTemplate = @"
export const config = {
"appName": "$AppName",
"tenantId": "$tenantId",
"clientId": "$appId"
};
"@
Write-Output $configTemplate

View File

@@ -42,15 +42,21 @@ function main() {
# Find the app by name # Find the app by name
APP_ID=$(az ad app list --display-name "$APP_NAME" --query "[0].appId" -o tsv) APP_ID=$(az ad app list --display-name "$APP_NAME" --query "[0].appId" -o tsv)
if [[ -n "$APP_ID" ]]; then if [[ -n "$APP_ID" ]]; then
echo "Error: Application '$APP_NAME' already exists." local USER_CONFIRMATION
exit 1 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 fi
# Create the app # Create the app when it does not already exist.
APP_ID=$(az ad app create --display-name "$APP_NAME" --query "appId" -o tsv)
if [[ -z "$APP_ID" ]]; then if [[ -z "$APP_ID" ]]; then
echo "Error: Failed to create application '$APP_NAME'." APP_ID=$(az ad app create --display-name "$APP_NAME" --query "appId" -o tsv)
exit 1 if [[ -z "$APP_ID" ]]; then
echo "Error: Failed to create application '$APP_NAME'."
exit 1
fi
fi fi
local M365_GRAPH_APP_ID="00000003-0000-0000-c000-000000000000" local M365_GRAPH_APP_ID="00000003-0000-0000-c000-000000000000"
@@ -94,25 +100,26 @@ function main() {
EOF EOF
) )
local PUBLIC_CLIENT_REDIRECT_URIS_JSON local REQUIRED_RESOURCE_ACCESS_FILE
PUBLIC_CLIENT_REDIRECT_URIS_JSON=$(cat <<EOF REQUIRED_RESOURCE_ACCESS_FILE=$(mktemp)
[ echo "$REQUIRED_RESOURCE_ACCESS_JSON" > "$REQUIRED_RESOURCE_ACCESS_FILE"
"http://localhost",
"msal${APP_ID}://auth"
]
EOF
)
# Configure app to match "Azure Node Playground Public". # Configure app to match "Azure Node Playground Public".
az ad app update \ az ad app update \
--id "$APP_ID" \ --id "$APP_ID" \
--set signInAudience=AzureADMyOrg \ --sign-in-audience AzureADMyOrg \
isFallbackPublicClient=true \ --is-fallback-public-client true \
requiredResourceAccess="$REQUIRED_RESOURCE_ACCESS_JSON" \ --required-resource-accesses @"$REQUIRED_RESOURCE_ACCESS_FILE" \
publicClient.redirectUris="$PUBLIC_CLIENT_REDIRECT_URIS_JSON" \ --public-client-redirect-uris "http://localhost" "msal${APP_ID}://auth" \
web.implicitGrantSettings.enableAccessTokenIssuance=true \ --enable-access-token-issuance true \
web.implicitGrantSettings.enableIdTokenIssuance=true \ --enable-id-token-issuance true \
1>/dev/null 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. # Ensure service principal exists before granting tenant-wide admin consent.
az ad sp create --id "$APP_ID" 1>/dev/null 2>/dev/null || true az ad sp create --id "$APP_ID" 1>/dev/null 2>/dev/null || true
@@ -124,8 +131,26 @@ EOF
exit 1 exit 1
fi 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" echo "appId: $APP_ID"
cat <<EOF
export const config = {
"appName": "$APP_NAME",
"tenantId": "$TENANT_ID",
"clientId": "$APP_ID"
};
EOF
} }
main "$@" main "$@"