I am using https://github.com/microsoftgraph/msgraph-sdk-powershell, as I need Powershell 7 support for my script, the AzureAD module has a ton of issues in anything but Powershell 5 on Windows I am finding. Basically, I am trying to create an app registration in a B2C tenant. The problem I was having, was my script seemed fine but I wasn't able to grant any admin consent to any of the scopes defined. Then I noticed the issue - when you create an app registration in the portal it automatically gets a service principal, which New-MgApplication
does not do.
I have the below script which works, up until I try and assign the service principal to my app using New-MgServicePrincipalAppRoleAssignment
, where it breaks down with the error: New-MgServicePrincipalAppRoleAssignment_CreateExpanded: Not a valid reference update.
I am unsure if this is the function appropriate for my need or whether New-MgRoleManagementDirectoryRoleAssignment
is the correct function.
function Upsert-AppRegistration {
Param(
[string] $TemplateParametersFile,
[string] $ResourceGroupName
)
$templateParameters = Get-Content $TemplateParametersFile | ConvertFrom-Json
$customerName = $templateParameters.parameters.customerName.value
$deploymentIdentifier = $templateParameters.parameters.deploymentIdentifier.value
$b2cTenantId = $templateParameters.parameters.b2cTenantId.value
$b2cTenantName = $templateParameters.parameters.b2cTenantName.value
$GraphConnection = Connect-Graph -TenantId $b2cTenantId -Scopes "User.Read","User.ReadWrite.All","Mail.ReadWrite",`
"Directory.ReadWrite.All","Chat.ReadWrite", "People.Read", `
"Group.Read.All", "Directory.AccessAsUser.All", "Tasks.ReadWrite", `
"Sites.Manage.All"
[string[]]$webRedirectUris =
"https://localhost:5050/LoginView",
"https://localhost:5050/DashboardView",
"https://localhost:5050/UsersView",
"https://localhost:5050/OrdersView"
# Our custom app.login scope for delegated permissions from front-end login
$oauth2PermissionScopes = @{
"Id" = [guid]::NewGuid().guid
"Value" = "app.login"
"AdminConsentDescription" = "This will provide the application access to login"
"AdminConsentDisplayName" = "Admin delegated login"
"IsEnabled" = $true
"Type" = "Admin"
}
[object[]]$appLoginScope = @{
"Id" = $oauth2PermissionScopes.Id
"Type" = "Scope"
}
# Microsoft.Graph ResourceAccess scopes and roles
$mgOfflineAccessScope = @{
"Id" = "7427e0e9-2fba-42fe-b0c0-848c9e6a8182"
"Type" = "Scope"
}
$mgOpenidScope = @{
"Id" = "37f7f235-527c-4136-accd-4a02d197296e"
"Type" = "Scope"
}
$mgDirectoryReadWriteAllRole = @{
"Id" = "19dbc75e-c2e2-444c-a770-ec69d8559fc7"
"Type" = "Role"
}
$mgResourceAccess = $mgOfflineAccessScope, $mgOpenidScope, $mgDirectoryReadWriteAllRole
[object[]]$requiredResourceAccess = @{
"ResourceAppId" = "00000003-0000-0000-c000-000000000000"
"ResourceAccess" = $mgResourceAccess
}
$mgApplicationParams = @{
"DisplayName" = "${customerName}-${deploymentIdentifier}"
"ApiOauth2PermissionScopes" = $oauth2PermissionScopes
"ApiRequestedAccessTokenVersion" = 2
"ImplicitGrantSettingEnableAccessTokenIssuance" = $true
"ImplicitGrantSettingEnableIdTokenIssuance" = $true
"RequiredResourceAccess" = $requiredResourceAccess
"WebLogoutUrl" = "https://localhost:5050/LogoutView"
"WebRedirectUris" = $webRedirectUris
"IdentifierUris" = "https://$b2cTenantName.onmicrosoft.com/app"
}
# We need to create our application before we can add permissions to our custom scope
$mgApplication = New-MgApplication @mgApplicationParams
# Now our application has an Id so we can finish setting up the RequiredResourceAccess
$newRequiredResourceAccess = $requiredResourceAccess + @{
"ResourceAppId" = $mgApplication.AppId
"ResourceAccess" = $appLoginScope
}
# Azure doesn't always update immediately, make sure app exists before we try to update its config
$appExists = $false
while (!$appExists) {
Start-Sleep -Seconds 2
$appExists = Get-MgApplication -ApplicationId $mgApplication.Id
}
$mgApplicationParams.Add("ApplicationId", $mgApplication.Id)
$mgApplicationParams.RequiredResourceAccess = $newRequiredResourceAccess
Update-MgApplication @mgApplicationParams
$appServicePrincipal = New-MgServicePrincipal -AppId $mgApplication.AppId -Tags @("WindowsAzureActiveDirectoryIntegratedApp")
$result = New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $appServicePrincipal.Id `
-AppRoleId 19dbc75e-c2e2-444c-a770-ec69d8559fc7 `
-ResourceId 429a2356-9cdc-475e-8caf-cfe8b7c77db8 `
-PrincipalType "ServicePrincipal"
# @TODO Generate app client secret
$appClientSecret = "--SECRET--"
Write-Host "Created the app registration ${customerName}-${deploymentIdentifier} with client Id:",
$mgApplication.AppId -ForegroundColor Yellow
@{
"appClientId" = $mgApplication.AppId
"appClientSecret" = $appClientSecret
}
}
Turns out I did not need to assign a role to my service principal for it work and everything to show up correctly. It was a combination of Azure's UI being laggy and also key was adding the Tag in the service principal, which when I posted this I had not yet tested.