Add delegated permissions step

This commit is contained in:
2026-02-07 12:53:57 +01:00
parent f66e5985f7
commit aff7d88cfd
2 changed files with 61 additions and 96 deletions

View File

@@ -4,7 +4,6 @@
param( param(
[Alias("n")] [Alias("n")]
[string]$AppName, [string]$AppName,
[switch]$UsePowershellModules,
[Alias("h")] [Alias("h")]
[switch]$Help [switch]$Help
) )
@@ -16,7 +15,6 @@ function Show-Usage {
Write-Host "Usage: ./New-PublicClientApplication.ps1 -AppName <name>" Write-Host "Usage: ./New-PublicClientApplication.ps1 -AppName <name>"
Write-Host "Options:" Write-Host "Options:"
Write-Host " -AppName, -n <name> Application display name (required)" Write-Host " -AppName, -n <name> Application display name (required)"
Write-Host " -UsePowershellModules Use Az.Accounts/Az.Resources cmdlets instead of Azure CLI"
Write-Host " -Help, -h Show this help message and exit" Write-Host " -Help, -h Show this help message and exit"
} }
@@ -85,109 +83,66 @@ $azureServiceMgmtScopeId = "41094075-9dad-400e-a0bd-54e686782033"
$azureDevOpsAppId = "499b84ac-1321-427f-aa17-267ca6975798" $azureDevOpsAppId = "499b84ac-1321-427f-aa17-267ca6975798"
$azureDevOpsScopeId = "ee69721e-6c3a-468f-a9ec-302d16a4c599" $azureDevOpsScopeId = "ee69721e-6c3a-468f-a9ec-302d16a4c599"
if ($UsePowershellModules) { if (-not (Get-Command az -ErrorAction SilentlyContinue)) {
if (-not (Get-Command Get-AzADApplication -ErrorAction SilentlyContinue)) { throw "Azure CLI 'az' is required."
throw "Get-AzADApplication cmdlet not found. Install Az.Resources." }
}
if (-not (Get-Command New-AzADApplication -ErrorAction SilentlyContinue)) {
throw "New-AzADApplication cmdlet not found. Install Az.Resources."
}
if (-not (Get-Command Update-AzADApplication -ErrorAction SilentlyContinue)) {
throw "Update-AzADApplication cmdlet not found. Install Az.Resources."
}
$azContext = Get-AzContext # Find the app by name
if ($null -eq $azContext) { $existingAppId = az ad app list --display-name $AppName --query "[0].appId" -o tsv
throw "No Azure context found. Run Connect-AzAccount first." if ($LASTEXITCODE -ne 0) {
} throw "Failed to query existing applications."
}
if (-not [string]::IsNullOrWhiteSpace($existingAppId)) {
Write-Error "Application '$AppName' already exists."
exit 1
}
$existingApp = Get-AzADApplication -DisplayName $AppName -First 1 # Create the app
if ($null -ne $existingApp) { $appId = az ad app create --display-name $AppName --query "appId" -o tsv
Write-Error "Application '$AppName' already exists." if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($appId)) {
exit 1 throw "Failed to create application '$AppName'."
} }
$requiredResourceAccess = Get-RequiredResourceAccess ` $requiredResourceAccess = Get-RequiredResourceAccess `
-M365GraphAppId $m365GraphAppId ` -M365GraphAppId $m365GraphAppId `
-M365GraphScopeId $m365GraphScopeId ` -M365GraphScopeId $m365GraphScopeId `
-AzureDevOpsAppId $azureDevOpsAppId ` -AzureDevOpsAppId $azureDevOpsAppId `
-AzureDevOpsScopeId $azureDevOpsScopeId ` -AzureDevOpsScopeId $azureDevOpsScopeId `
-AzureServiceMgmtAppId $azureServiceMgmtAppId ` -AzureServiceMgmtAppId $azureServiceMgmtAppId `
-AzureServiceMgmtScopeId $azureServiceMgmtScopeId -AzureServiceMgmtScopeId $azureServiceMgmtScopeId | ConvertTo-Json -Depth 10 -Compress
$webConfig = @{ $publicClientRedirectUris = @(
implicitGrantSettings = @{ "http://localhost",
enableAccessTokenIssuance = $true "msal${appId}://auth"
enableIdTokenIssuance = $true ) | ConvertTo-Json -Compress
}
}
# Create first to obtain appId needed for msal<appId>://auth redirect URI. # Configure app to match "Azure Node Playground Public".
$newApp = New-AzADApplication ` az ad app update `
-DisplayName $AppName ` --id $appId `
-SignInAudience "AzureADMyOrg" ` --set `
-IsFallbackPublicClient ` "signInAudience=AzureADMyOrg" `
-PublicClientRedirectUri @("http://localhost") ` "isFallbackPublicClient=true" `
-RequiredResourceAccess $requiredResourceAccess ` "requiredResourceAccess=$requiredResourceAccess" `
-Web $webConfig "publicClient.redirectUris=$publicClientRedirectUris" `
"web.implicitGrantSettings.enableAccessTokenIssuance=true" `
"web.implicitGrantSettings.enableIdTokenIssuance=true" | Out-Null
if ($null -eq $newApp -or [string]::IsNullOrWhiteSpace($newApp.AppId)) { if ($LASTEXITCODE -ne 0) {
throw "Failed to create application '$AppName' via Az.Resources." throw "Failed to configure application '$AppName'."
} }
$appId = $newApp.AppId # Azure CLI is used to grant admin consent.
Update-AzADApplication ` # Ensure service principal exists before granting tenant-wide admin consent.
-ApplicationId $appId ` az ad sp create --id $appId | Out-Null
-SignInAudience "AzureADMyOrg" ` if ($LASTEXITCODE -ne 0) {
-IsFallbackPublicClient ` throw "Failed to ensure service principal exists for '$AppName' ($appId)."
-RequiredResourceAccess $requiredResourceAccess ` }
-PublicClientRedirectUri @("http://localhost", "msal${appId}://auth") `
-Web $webConfig | Out-Null
} else {
# Find the app by name
$existingAppId = az ad app list --display-name $AppName --query "[0].appId" -o tsv
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 # Grant admin consent for configured delegated permissions.
$appId = az ad app create --display-name $AppName --query "appId" -o tsv az ad app permission admin-consent --id $appId | Out-Null
if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrWhiteSpace($appId)) { if ($LASTEXITCODE -ne 0) {
throw "Failed to create application '$AppName'." throw "Failed to grant admin consent for '$AppName' ($appId)."
}
$requiredResourceAccess = Get-RequiredResourceAccess `
-M365GraphAppId $m365GraphAppId `
-M365GraphScopeId $m365GraphScopeId `
-AzureDevOpsAppId $azureDevOpsAppId `
-AzureDevOpsScopeId $azureDevOpsScopeId `
-AzureServiceMgmtAppId $azureServiceMgmtAppId `
-AzureServiceMgmtScopeId $azureServiceMgmtScopeId | ConvertTo-Json -Depth 10 -Compress
$publicClientRedirectUris = @(
"http://localhost",
"msal${appId}://auth"
) | ConvertTo-Json -Compress
# 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
if ($LASTEXITCODE -ne 0) {
throw "Failed to configure application '$AppName'."
}
} }
Write-Host "Created application '$AppName'" Write-Host "Created application '$AppName'"

View File

@@ -114,6 +114,16 @@ EOF
web.implicitGrantSettings.enableIdTokenIssuance=true \ web.implicitGrantSettings.enableIdTokenIssuance=true \
1>/dev/null 1>/dev/null
# Ensure service principal exists before granting tenant-wide admin consent.
az ad sp create --id "$APP_ID" 1>/dev/null 2>/dev/null || true
# Grant admin consent for configured delegated permissions.
az ad app permission admin-consent --id "$APP_ID" 1>/dev/null
if [[ $? -ne 0 ]]; then
echo "Error: Failed to grant admin consent for '$APP_NAME' ($APP_ID)."
exit 1
fi
echo "Created application '$APP_NAME'" echo "Created application '$APP_NAME'"
echo "appId: $APP_ID" echo "appId: $APP_ID"
} }