1

I have an Azure AD Application where I need to add an extra appRole in the appRoles section within the service principal with Powershell. I use an Invoke-RestMethod to the Graph API with the following API Url: https://graph.microsoft.com/beta/servicePrincipals/AppID

The Invoke-RestMethod returns an PSCustomObject, and then I add another PSCustomObject in the appRoles section. I then convert the PSCustomObject to JSON and want to write back the JSON to the service principal. The problem is when I want to write the JSON back to the service principal I get the error message:

Invoke-RestMethod : The remote server returned an error: (400) Bad Request.

I've tried to do this also with the Graph explorer and then I get the error message:

"An unexpected 'PrimitiveValue' node was found when reading from the JSON reader. A 'StartArray' node was expected."

I think the same problem is also here in C#: Getting Bad Request error while updating email category with Office 365 API and HttpClient in C#

When I do a Get in Graph Explorer the every appRole is displayed like this:

{
  "allowedMemberTypes": [
    "User"
  ],
  "description": "TEST-ALLOWALL",
  "displayName": "TEST-ALLOWALL",
  "id": "00000000-0000-0000-0000-00000000",
  "isEnabled": true,
  "origin": "ServicePrincipal",
  "value": "ARNROLEVALUE"
},

When I do an Invoke-RestMethod and then ConvertTo-Json, every appRole is displayed like this:

{
  "allowedMemberTypes":  "User",
  "description":  "TEST-ALLOWALL",
  "displayName":  "TEST-ALLOWALL",
  "id":  "00000000-0000-0000-0000-00000000",
  "isEnabled":  true,
  "origin":  "ServicePrincipal",
  "value":  "ARNROLEVALUE"
},

How can I make sure the Invoke-RestMethod keeps the allowedMemberTypes value type an array/list like ["User"] instead of the value "User"?

And how can I make my own PSCustomObject allowedMembertypes value and arraylist so I can add it to the service principal?

This is the code I am using

$apiUrl = 'https://graph.microsoft.com/beta/servicePrincipals/000000-0000-0000-0000-00000000000'
$Data = Invoke-RestMethod -Headers $graphAPIReqHeader -Uri $apiUrl -Method Get

$obj = New-Object -TypeName PSObject
$obj | Add-Member -MemberType NoteProperty -Name allowedMemberTypes -Value "User"
$obj | Add-Member -MemberType NoteProperty -Name description -Value $RoleName
$obj | Add-Member -MemberType NoteProperty -Name displayName -value $RoleName
$obj | Add-Member -MemberType NoteProperty -Name id -value $Id
$obj | Add-Member -MemberType NoteProperty -Name isEnabled -value "true"
$obj | Add-Member -MemberType NoteProperty -Name origin -value "ServicePrincipal"
$obj | Add-Member -MemberType NoteProperty -Name value -value $Value

$Data.appRoles += $obj
$NewJson = $Data | ConvertTo-Json
$NewData = Invoke-RestMethod -Headers $graphAPIReqHeader -Uri $apiUrl -Body $NewJson -Method Patch -ContentType 'application/json' 

ASA
  • 35
  • 1
  • 8
  • 1
    Checkout the `-depth` parameter of convert-json. https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/convertto-json?view=powershell-6 – Moerwald Jun 06 '19 at 12:06
  • Thanks Moerwald! It works for the PsCustomObject i've received with Invoke-RestMethod with ConvertTo-Json -Depth 4. But how can I also create an string array for the PSCustomObject I want to add? $obj | Add-Member -MemberType NoteProperty -Name allowedMemberTypes -Value "User" – ASA Jun 06 '19 at 13:20

1 Answers1

0
$input = @"
{
  "allowedMemberTypes": [
    "User"
  ],
   "description": "TEST-ALLOWALL",
   "displayName": "TEST-ALLOWALL",
  "id": "00000000-0000-0000-0000-00000000",
  "isEnabled": true,
  "origin": "ServicePrincipal",
  "value": "ARNROLEVALUE"
}
"@

$jObject = $input | convertfrom-json

$psObj = [Pscustomobject] @{
   AllowedMemberTypes = $jObject.allowedMemberTypes 
}
 $psObj.AllowedMemberTypes.Gettype()

$psObj.AllowedMemberTypes.Gettype() shows that AllowedMemberTypes is of type array.

You can find the code online, and play around with it.

Hope that helps.

Moerwald
  • 10,448
  • 9
  • 43
  • 83
  • Thank you for your answer! I works ok now. Only thing I had to do was to remove -depth 10 . Seems that ConvertFrom-Json doesn't have to Depth parameter, only ConvertTo-Json – ASA Jun 07 '19 at 00:16