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