Updating Extension Attributes for Azure AD Registered Devices with the Microsoft Graph PowerShell SDK

Registered Devices and Azure AD

According to Microsoft, the goal for Azure AD registered devices (workplace joined devices) is “to provide your users with support for bring your own device (BYOD) or mobile device scenarios. In these scenarios, a user can access your organization’s resources using a personal device.” Personally, I haven’t paid registered devices much attention over the years. Other topics occupied my time, and apart from going through the joining process to allow the organization to manage the device, ignored their existence.

Devices occupy their own area in the Azure AD admin center (Figure 1). The details displayed for each device are those gathered when the device registers with Azure AD. This accounts for some of the funky default device names generated by Windows. Azure AD doesn’t update devices records with details of O/S upgrades, so many of my devices appear to run Windows 10 when they’ve long since acquired Windows 11. The Azure AD admin center concentrates mainly on organizing device identities, which is what you’d expect from a directory.

Azure AD registered devices in the Azure AD admin center
Figure 1: Azure AD registered devices in the Azure AD admin center

Setting Extension Attributes for Azure AD Registered Devices

In any case, I thought that there might be some way to exploit the registered devices in Azure AD., similar in concept to the way that Exchange administrators often use custom attributes to mark mailboxes (here’s an example of using custom attributes to drive the membership of dynamic distribution groups).

This led me to the Graph API for Devices and a note in that page about using extension attributes. Organizations commonly use Azure AD extension attributes to store extra information about user objects. They’re also available for device objects, and it’s convenient to be able to use the extension attributes to store information that help administrators know who uses a device. Fifteen extension attributes (ExtensionAttribute1 through ExtensionAttribute15) are available.

It seemed to make sense to use the extension attributes to make the entries for registered devices more useful. I decided to populate six of the extension attributes with information about the user who registered a device. It’s not always the case that the registered owner is still the person who uses a device, but there’s a high probability that it is, especially in BYOD scenarios.

To test the theory, I wrote a script using the Microsoft Graph PowerShell SDK to:

  • Find all registered devices with the Get-MgDevice cmdlet.
  • For each device, extract the identifier for the owner’s Azure AD account. This is stored in an odd manner in the device record (at least, Microsoft could make it much simpler to find and use the identifier).
  • Use the Get-MgUser cmdlet to check the identifier against Azure AD and retrieve user details if a match is successful. The lookup fails if the user is no longer in Azure AD or their account belongs to another tenant (Azure AD can register devices for guest users).
  • Run Update-MgDevice to populate the extension attributes when we have an account match.

Connect-MgGraph -Scopes "Directory.ReadWrite.All"
Select-MgProfile Beta
[array]$Devices = Get-MgDevice -All

ForEach ($Device in $Devices) {
  If ($Device.PhysicalIds.count -gt 0) {
    Foreach ($X in $Device.PhysicalIds) { If ($X.SubString(0,10) -eq "[USER-GID]") { $UserGuid = $X } }
    $UserId = $UserGuid.substring(11,36)
    If ($UserId) { #We found a user identifier - try to resolve it against Azure AD
       [array]$User = Get-MgUser -UserId $UserId -ErrorAction SilentlyContinue }
       If ($User) { # Found a user in Azure AD
         Write-Host ("Device {0} owned by {1}" -f $Device.DisplayName, $User.DisplayName)
         $Attributes = @{
          "onPremisesExtensionAttributes" = @{
            "extensionAttribute1" = $User.DisplayName
            "extensionAttribute2" = $User.UserPrincipalName
            "extensionAttribute3" = $User.MobilePhone
            "extensionAttribute4" = $User.Department 
            "extensionAttribute5" = $User.City
            "extensionAttribute6" = $User.Country }
         }  | ConvertTo-Json
      Update-MgDevice -DeviceId $Device.Id -BodyParameter $Attributes 
       Else { Write-Host ("Device {0} owned by unknown user {1}" -f $Device.DisplayName, $UserId ) }
  } # End If Device PhysicalsId
} #End Foreach

Using Extension Attributes for Azure AD Registered Devices

After populating the device attributes, their values are available through the Azure AD admin center (Figure 2).

Figure 2: Populated extension attributes for an Azure AD registered device

Even better, it’s easy to apply a filter against the extension attributes to find a subset of devices. In this example, I find all devices where the value of extensionAttribute6 is “Ireland.”

[array]$IrelandDevices = Get-MgDevice -Filter "extensionAttributes/extensionAttribute6 eq 'Ireland'" -CountVariable IrelandCount -ConsistencyLevel eventual

Custom Attributes for All

Even those running device management software like Intune might find value in being able to assign custom values to registered devices through PowerShell. The possibilities are endless. At least, that’s what I’ve heard.

Learn about exploiting Azure AD and PowerShell by subscribing to the Office 365 for IT Pros eBook. Use our experience to understand what’s important and how best to protect your tenant.

30 Replies to “Updating Extension Attributes for Azure AD Registered Devices with the Microsoft Graph PowerShell SDK”

  1. Hi Tony, great article once again! I was wondering earlier on about these extension attributes for another use case. Would it be possible to extract some kind of uniquie id (max address?) from the azure ad registration? To explain: I ‘d like to flag specific devices for conditional access policies to apply. Is this even possible? Would appreciate if you could me into a direction.

      1. are you sure that device filtering by extensionAttributes works for Azure AD Registered devices?
        I am struggling with this right now and it seems NOT

      2. Yes. I’m certain. You can filter against extension attributes. These are complex queries so make sure that you pass the ConsistencyLevel parameter.

      3. according to this table, Microsoft support and my tests, it turns out that not necessarily.
        CA policies for Azure AD Registered devices do not see the extensionAttributes parameter

        Have you tested that it works?
        Are you just talking theoretically?
        Because from my practical tests, it doesn’t work for Azure AD Registered devices

      4. I am absolutely sure that it is possible to filter against extension attributes for registered devices. You can do this with the Get-MgDevice cmdlet.

        As to CA policies, my authority on this point came from https://www.petervanderwoude.nl/post/using-filters-for-devices-as-condition-in-conditional-access-policies/. This points to the Microsoft documentation https://learn.microsoft.com/en-us/azure/active-directory/conditional-access/concept-condition-filters-for-devices which includes:

        Policy 2: All users with the directory role of Global Administrator, accessing the Microsoft Azure Management cloud app, excluding a filter for devices using rule expression device.extensionAttribute1 equals SAW and for Access controls, Block. Learn how to update extensionAttributes on an Azure AD device object.

        The documentation then goes on to explain how to set the filter using ExtensionAttribute1.

        Did you read that documentation and attempt to follow it? If you can’t make it work, then you can go to Microsoft Support and ask them why it doesn’t work. It is possible that a change has been made by the Azure AD subsequent to the publication of the online material.

      5. Hello

        I currently have a ticket in Microsoft support.
        Their engineer remotely waltzed with me for 3 hours and it doesn’t work for registered devices

        apparently this tablet says so, but it is very vague and confusing.

        Registered device not manager by Intune
        Yes, if criteria are met. When extensionAttributes1-15 are used, the policy will apply if device is compliant or Hybrid Azure AD joined

        You cannot have a non-inTune managed and compliant device registered. It is impossible.

  2. Nevermind

    > $params = @{
    > “extensionAttributes” = @{
    > “extensionAttribute2” = “”
    > }
    > }
    > update-MgDevice -DeviceId GUID -BodyParameter ($params | ConvertTo-Json)

      1. This doesn’t seem to work any more! I can modify the values but passing empty quotes or Null wouldn’t change or remove them. What am I missing?!

        Connect-MgGraph -Scopes “Directory.AccessAsUser.All”
        Select-MgProfile Beta
        Import-Module Microsoft.Graph.Identity.DirectoryManagement
        $params = @{
        “extensionAttributes” = @{
        “extensionAttribute2” = “”
        update-MgDevice -DeviceId $DeviceID -BodyParameter ($params | ConvertTo-Json)

        (Get-MgDevice -DeviceId $DeviceID).ExtensionAttributes.ExtensionAttribute2


      2. Thanks for the advice and link to your other article Tony! Passing space in ” ” fixed it. What a great hasslle. It’s I couldn’t find that anywhere and even Mark’s example up here has it as “” and not ” “!

        You also said in your reply to Mark, OR pass Null! How do you do that? “extensionAttribute2” = $Null certainly didn’t work.

        How about for Graph requests? I tried both “extensionAttribute2″ : ” ” and “extensionAttribute2” : Null in MSGrap-Explorer’s Request body and neither worked.

        I appreciate your help.

      3. Nope, not only neither $Null nor $null worked, but also I think I spoke too soon, because even “extensionAttribute2” = ” ” doesn’t remove the property, it just erases its value with a single space character!

        I need to delete/remove “extensionAttribute2” all together. I can swear “” worked before. Could it be bug introduced in recent updates? none of the methods seem to work. Back to the drawing board. Please let me know if you can think of anything I might be missing.

        Thank you so much.

  3. Tony, would you happen to know if any of these attributes can be synced back onprem as part of the AADConnect Device Write back?

  4. Hey Tony,
    Great article and has me thinking about how best to use this. Is it possible to automatically assign an extension attribute to all AD computer enrolled into Intune with a particular extension attribute? Or to possible script this in bulk?
    Thanks in advance.

    1. I’m sure you can script this (at least, I think you can). I don’t know if automatic assignment is possible. I suspect not because these attributes are intended for use by customers for their own purposes. You have total control over the attributes, but you need to maintain them.

    1. >>> means that PowerShell is waiting for you to complete a command. Did you paste all the code into the command window? Do you know what line it’s failing on?

  5. Hi Tony, great looking script which I could make lots of use from it. I’ve had a play around with it. Unfortunately I cannot get it to work and the reason for that is all my phyicalids are null. I’ve had a look about the internet and not sure how this field is populated have you any idea how they are?

    Any other question is could a similar script do the same using something like OperatingSystem ?

    1. I’m not sure about why the physical device ids aren’t showing up – maybe it’s something as simple as connecting to the V1.0 endpoint instead of the beta.

      Try running Select-MgProfile beta and then Get-MgDevice.

      I haven’t looked into getting details of operating systems (yet).

      1. Hey Tony, Managed to get what I wanted with the guidance of your script above. Thanks for your help and thank you for the other post, again something very helpful.

        My script ended up like below

        Select-MgProfile “Beta”

        [array]$AllUsers = Get-AzADUser

        ForEach ($User in $AllUsers){
        # All devices assigned to each owner
        [array]$UserDevices = get-mguserowneddevice -UserId $User.Id
        ForEach ($UserDevice in $UserDevices){
        $Device = Get-MgDevice -DeviceId $UserDevice.Id
        if(($device.OperatingSystem -like ‘iOS’) -or ($device.OperatingSystem -like ‘iphone’)){
        $uri = $null
        $uri = https://graph.microsoft.com/beta/devices/ + $device.id

        $json = @{
        “extensionAttributes” = @{
        “extensionAttribute1” = $User.UserPrincipalName
        “extensionAttribute2” = $User.MobilePhone
        “extensionAttribute3” = $User.OfficeLocation

        } | ConvertTo-Json
        Invoke-MgGraphRequest -Uri $uri -Body $json -Method PATCH -ContentType “application/json”


  6. Hi Everyone,
    i am now trying for days to get the script to work, but i am stuck at executing the script and getting this error

    update-MgDevice : Insufficient privileges to complete the operation.
    FullyQualifiedErrorId : Authorization_RequestDenied,Microsoft.Graph.PowerShell.Cmdlets.UpdateMgDevice_Update1

    Can anyone let me know which Azure-AD Role i need to write Extension Attributes ? Currently i have the Cloud Device Administrator Role activated.

    Thanks a lot for any help.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.