Updating Extension Attributes for Entra ID Registered Devices with the Microsoft Graph PowerShell SDK

Registered Devices and Entra ID (Azure AD)

Updated 8 September 2023

According to Microsoft, the goal for Entra ID 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 Entra ID admin center (Figure 1). The details displayed for each device are those gathered when the device registers with Entra ID. This accounts for some of the funky default device names generated by Windows. Entra ID 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 Entra ID admin center concentrates mainly on organizing device identities, which is what you’d expect from a directory.

Entra ID registered devices in the Entra ID admin center
Figure 1: Entra ID registered devices in the Entra ID admin center

Setting Extension Attributes for Entra ID Registered Devices

In any case, I thought that there might be some way to exploit the registered devices in Entra ID, 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 Entra ID 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 user’s 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 Entra ID and retrieve user details if a match is successful. The lookup fails if the user is no longer in Entra ID or their account belongs to another tenant (Entra ID 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, Device.Read.All
[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 Entra ID
       [array]$User = Get-MgUser -UserId $UserId -ErrorAction SilentlyContinue }
       If ($User) { # Found a user in Entra ID
         Write-Host ("Device {0} owned by {1}" -f $Device.DisplayName, $User.DisplayName)
         $Attributes = @{
          "ExtensionAttributes" = @{
            "extensionAttribute1" = $User.DisplayName
            "extensionAttribute2" = $User.UserPrincipalName
            "extensionAttribute3" = $User.MobilePhone
            "extensionAttribute4" = $User.Department 
            "extensionAttribute5" = $User.City
            "extensionAttribute6" = $User.Country }
         }  | ConvertTo-Json
      Update-MgBetaDevice -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 Entra ID Registered Devices

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

Populated extension attributes for an Entra ID registered device
Figure 2: Populated extension attributes for an Entra ID 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 Entra ID (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.

43 Replies to “Updating Extension Attributes for Entra ID 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.
        https://learn.microsoft.com/en-us/azure/active-directory/conditional-access/concept-condition-filters-for-devices#policy-behavior-with-filter-for-devices

        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
        $DeviceID=”7b280351-2f6f-4028-ae6e-d7f598666767″
        $params = @{
        “extensionAttributes” = @{
        “extensionAttribute2” = “”
        }
        }
        update-MgDevice -DeviceId $DeviceID -BodyParameter ($params | ConvertTo-Json)

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

        Test

      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

        Connect-MgGraph
        Select-MgProfile “Beta”

        Connect-AzAccount
        [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’)){
        $User.OfficeLocation
        $uri = $null
        $uri = https://graph.microsoft.com/beta/devices/ + $device.id
        $uri

        $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.
    Chris

  7. Not sure if I am missing something here or if the script is no longer valid, but getting the error “Update-MgDevice : Invalid property ‘onPremisesExtensionAttributes’.”

    1. 1. The script was written for the SDK V1. The Select-MgProfile command is no longer needed.
      2. The beta version of Update-MgDevice is needed to update the attributes (so use Update-MgBetaDevice).
      3. Microsoft changed the property name in SDK V2.

      Try now.

  8. Hi,
    I’m having trouble running your script. It keeps asking me to log in over and over again. If I close the login box, it says:
    Get-MgDevice : Code: generalException
    Message: Unexpected exception occurred while authenticating the request.
    At line:2 char:1
    + [array]$Devices = Get-MgDevice -All
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Get-MgDevice_List1], AuthenticationException
    + FullyQualifiedErrorId : Microsoft.Graph.PowerShell.Cmdlets.GetMgDevice_List1.
    And if I close the login box again, it says Device XXXX owned by unknown user xxxx-xxx-xxx-xxxx-xxxxxx.

  9. hi @tony, in your script, the device ID value is link to which intune device field? because this is not the Intune Device ID or the Microsoft Entra Device ID in intune. i dont see this value in the device profile
    Thanks

    1. AFAIK, the id is the identifier registered in Entra ID for a device. I can’t recall off hand exactly how this matches up with the Intune information. I do recall that it seemed like Microsoft made the connections more difficult that they should be.

  10. Hey Tony,

    Thank you for writing this up. Trying to get this going because it will be pivotal for our deployment strategy in the current environment I’m working in. I have started testing this by changing the “-All” parameter to “-DeviceID *Entra ObjectID*” (couldn’t actually get it to run without error using the actual Entra DeviceID).

    The issue I’m running into is that it comes back as Unknown User and provides my User’s Object ID. I have tried some workarounds like changing the account I’m using to run the script, tried a couple of different machines, and it keeps coming back with my User Object ID.

    It would be much appreciated if you had any direction here.

      1. Yeah that was our exact findings. Unsure why it’s still coming back as Unknown User and failing to add the extension attribute. It’s also pulling my User Object ID even if I’m not the owner of the device.

Leave a Reply

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