How to retrieve values of all directory extensions in the Microsoft Graph API

Directory extensions

Directory extensions provide a strongly typed, discoverable and filterable extension experience for the following directory objects:

  • users
  • groups
  • applications
  • administrative units
  • organization

Directory extensions are registered on an application and explicitly target one or more directory objects mentioned aobve.

The extensions properties become immediately accessible in the tenant once the application has been consented.

The naming of the directory extension properties, extension_{appId-without-hyphens}_{extensionProperty-name}, makes the directory extensions hard to retrieve.

Retrieve all directory extensions and associated data

What if you want to retrieve all directory extensions and associated data on a specific directory object?

The Microsoft Graph API exposes the endpoint POST /v1.0/directoryObjects/microsoft.graph.getAvailableExtensionProperties which returns all available directory extensions definitions including those defined by multi-tenant apps..

Microsoft Graph PowerShell SDK has the cmdlet Get-MgDirectoryObjectAvailableExtensionProperty that calls the same endpoint.

Import-Module Microsoft.Graph.DirectoryObjects

Get-MgDirectoryObjectAvailableExtensionProperty

It gives you the names of the extension properties and the target objects. The endpoint doesn't support filtering by targetObjects, so you will need to filter the target resource in your code.

$targetObject = 'user'

$properties = @()
$properties += 'id'
$properties += 'displayName'

$extensionProperties = Get-MgDirectoryObjectAvailableExtensionProperty

$extensionProperties | ForEach-Object {
    if ($_.TargetObjects -contains $targetObject) {
        $properties+=$_.Name
    }
}
$selectedProperties = $properties -join ','

What is left is to retrive the extension properties and associated data on a specific directory object. You need to construct the URI with $select query parameter and specify extensions properties names.

$directoryObjects = @()
$URI="https://graph.microsoft.com/v1.0/directoryObjects/microsoft.graph.$($targetObject)?`$select=$($selectedProperties)"
$response = Invoke-MgGraphRequest -Method GET -Uri $URI
$response.value | ForEach-Object {
    $directoryObjects+=$_
}
while ($response.'@odata.nextLink') {
    $response = Invoke-MgGraphRequest -Method GET -Uri $response.'@odata.nextLink'
    $response.value | ForEach-Object {
        $directoryObjects+=$_
    }
}
$directoryObjects | ConvertTo-Json

Invoke-MgGraphRequest doesn't handle pagination, so you need to handle it manually by checking @odata.nextLink property.

The endpoint /v1.0/directoryObjects/microsoft.graph.<resource> it's an alternative to /v1.0/users, /v1.0/groups, /v1.0/applications, /v1.0/directory/administrativeUnits and /v1.0/organization.

The output will look like this:

[
  {
    "displayName": "Adele Vance",
    "id": "61b0c52f-a902-4769-9a09-c6628335b00a",
    "extension_81a3f040537248bbac282b168a19eec6_jobGroupDate": "2024-09-05T11:12:13Z"
  },
  {
    "displayName": "Alex Wilber",
    "id": "52f26d18-d151-434f-ae14-a4a83122b2b2",
    "extension_7139ef5115054b29a682f0720c4c95e2_ext2": 5624,
    "extension_7139ef5115054b29a682f0720c4c95e2_ext4": [
      false,
      true
    ]
  },
  {
    "displayName": "Car_AstonMartin_7Z70007",
    "id": "eddffd2c-20d6-49b2-b1ac-bcc430bc95de",
    "extension_7139ef5115054b29a682f0720c4c95e2_ext13": [
      "Employee Car"
    ]
  },
  {
    "displayName": "Car_Porsche",
    "id": "eae212d4-341e-447f-9241-4acba2a7dcf1",
    "extension_7139ef5115054b29a682f0720c4c95e2_ext13": [
      "CEO Car"
    ]
  },
  {
    "displayName": "Diego Siciliani",
    "id": "5f91f951-7305-4a27-9b63-7b00906de09f",
    "extension_7139ef5115054b29a682f0720c4c95e2_ext19": [
      "Project Y",
      "Project X"
    ]
  },
  {
    "displayName": "Grady Archie",
    "id": "882a04af-f9e0-47dd-884b-d195980aa185",
    "extension_7139ef5115054b29a682f0720c4c95e2_ext19": [
      "Project Y",
      "Project X"
    ],
    
    "extension_7139ef5115054b29a682f0720c4c95e2_ext20": [
      "Monitor",
      "PC"
    ],
    
    "extension_7139ef5115054b29a682f0720c4c95e2_ext21": [
      "2024",
      "2023",
      "2022",
      "2021"
    ]
  }
]

The whole script:

Connect-MgGraph

# user, group, application, device, administrativeUnit, organization
$targetObject = 'user'

$properties = @()
$properties += 'id'
$properties += 'displayName'

$extensionProperties = Get-MgDirectoryObjectAvailableExtensionProperty

$extensionProperties | ForEach-Object {
    if ($_.TargetObjects -contains $targetObject) {
        $properties+=$_.Name
    }
}
$selectedProperties = $properties -join ','

$directoryObjects = @()
$URI="https://graph.microsoft.com/v1.0/directoryObjects/microsoft.graph.$($targetObject)?`$select=$($selectedProperties)"
$response = Invoke-MgGraphRequest -Method GET -Uri $URI
$response.value | ForEach-Object {
    $directoryObjects+=$_
}
while ($response.'@odata.nextLink') {
    $response = Invoke-MgGraphRequest -Method GET -Uri $response.'@odata.nextLink'
    $response.value | ForEach-Object {
        $directoryObjects+=$_
    }
}
$directoryObjects | ConvertTo-Json

Disconnect-MgGraph
0
Buy Me a Coffee at ko-fi.com
An error has occurred. This application may no longer respond until reloaded. Reload x