← Blog |

How to Create Query Based “Collections” In Intune

By John Marcum

How to Create Query Based “Collections” In Intune

In Microsoft Configuration Manager (ConfigMgr), collections allow administrators to organize resources into manageable units for easier, large-scale management. Collections can be customized to meet specific client needs, enabling tasks such as deploying applications, managing compliance settings, and installing updates. According to the ConfigMgr documentation, creating custom collections—rather than using the default “All Systems” collection—is best practice for effectively targeting specific devices or users.

In ConfigMgr, we can create dynamic collections by defining query rules. Some examples from Microsoft documentation include:

  • Computers with a specific software package installed
  • Devices of a specific type

A great reference for ConfigMgr queries is this blog post by Anders Rødland, which includes dynamic collections like

  • “All SCCM client computers with less than 1GB free disk space on C:”
  • “Collection of computers with failing hard drive”
  • “Query based collection based on IP subnet”
  • “All Physical Systems”
  • “Computers with AVG and Security Essentials Antivirus”

However, in Intune, creating similar dynamic collections based on device or user properties, such as hardware information or specific software installations, isn’t directly supported.

For those who started managing devices in Intune, the absence of ConfigMgr-style collections may go unnoticed. But for those of us who transitioned from ConfigMgr, this limitation is a significant hurdle. In fact, during one session that I attended at MMS Flamingo Edition 2024, a Microsoft presenter fielded many questions about this topic, with participants eager to see these features in Intune.

This blog post presents an alternative solution to help bridge the gap between ConfigMgr and Intune’s dynamic device and user grouping capabilities. I’ve created an automated approach to build the equivalent of query-based collections in Intune using Entra ID groups, Power BI, Power Automate, and Logic Apps.

Note: This post serves as an encouragement to explore creative solutions to Intune limitations rather than waiting for Microsoft to address every shortcoming. Although PowerStacks will assist its customers in implementing this solution, I’ll outline the steps here for those who wish to tackle it independently.

The Solution Overview

This solution relies on four main components:

  1. BI for Intune for data extraction
  2. Power Automate flow for collecting and posting data
  3. Managed identity for secure access to Entra ID
  4. Logic App to orchestrate group membership changes

Let’s take a closer look at each component.

1. BI for Intune

Using Power BI Desktop, connect to the BI for Intune semantic model and create a simple table that lists the IDs of devices matching your criteria. For example, you can generate a table of all computers (Entra ID device ID’s) with “Zoom” installed. get dax query

This DAX query generates a list of device IDs, which we can use to populate a group in Entra ID. If you’re not a PowerStacks customer, you’ll need an alternative way to obtain this device information.

Once configured, export the DAX query, which should look something like this:

				SQL
DEFINE
    VAR __DS0FilterTable = TREATAS({"Zoom", "Zoom (64-bit)"}, 'App Inventory'[App Inventory Name])
    VAR __DS0Core = CALCULATETABLE(DISTINCT('Device'[Azure AD Device ID]), KEEPFILTERS(__DS0FilterTable))
    VAR __DS0PrimaryWindowed = TOPN(501, __DS0Core, 'Device'[Azure AD Device ID], 1)
EVALUATE
    __DS0PrimaryWindowed
ORDER BY
    'Device'[Azure AD Device ID]
		DEFINE
VAR __DS0FilterTable = TREATAS({"Zoom", "Zoom (64-bit)"}, 'App Inventory'[App Inventory Name])
VAR __DS0Core = CALCULATETABLE(DISTINCT('Device'[Azure AD Device ID]), KEEPFILTERS(__DS0FilterTable))
VAR __DS0PrimaryWindowed = TOPN(501, __DS0Core, 'Device'[Azure AD Device ID], 1)

EVALUATE __DS0PrimaryWindowed ORDER BY ‘Device’[Azure AD Device ID]

2. Power Automate Flow

The Power Automate flow queries the Power BI model to retrieve device IDs using the DAX query, applies a predefined group name, and posts the information to a Logic App. The flow is scheduled to run periodically. Here’s an example HTTP POST payload: automate flow

Here’s an example HTTP POST payload:

				JSON
{
  "type": "Http",
  "inputs": {
    "uri": "https://prod-02.westus2.logic.azure.com:443/workflows//triggers/When_a_HTTP_request_is_received/paths/invoke?api-version=2016-10-01&sp=%2Ftriggers%2FWhen_a_HTTP_request_is_received%2Frun&sv=1.0&sig=",
    "method": "POST",
    "headers": {
      "Content-type": "application/json"
    },
    "body": {
      "deviceIds": "@outputs('Select')",
      "groupName": "@variables('GroupName')"
    }
  }
}
		{

“type”: “Http”, “inputs”: { “uri”: “https://prod-02.westus2.logic.azure.com:443/workflows/<confidential_info>/triggers/When_a_HTTP_request_is_received/paths/invoke?api-version=2016-10-01&sp=%2Ftriggers%2FWhen_a_HTTP_request_is_received%2Frun&sv=1.0&sig=<confidential_info>”, “method”: “POST”, “headers”: { “Content-type”: “application/json” }, “body”: { “deviceIds”: “@outputs(‘Select’)”, “groupName”: “@variables(‘GroupName’)” } } }

3. Managed Identity

The managed identity provides the Logic App with the necessary permissions (“GroupMember.ReadWrite.All” and “Device.Read.All”) to interact with Entra ID securely. identity

4. Logic App

The Logic App receives the list of device IDs and the group name from the flow, checks for the group’s existence, and updates group membership accordingly. If the group exists, the Logic App retrieves the current group members, compares them to the provided list, and synchronizes any additions or removals. Finally, it sends an email summary of the changes.

As you can see from the screenshot below, the Logic App is quite extensive and complex, with over 80 hours invested in its development. Because of this, I opted not to provide a detailed step-by-step guide, as such a blog would be incredibly lengthy. logic app

Logic App Workflow Code

Below is an example of the JSON code for the Logic App workflow. This code controls the logic of creating, updating, and maintaining Entra ID groups based POST from the Flow. (Code might vary based on your exact requirements.)

				JSON
{
    "definition": {
        "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
        "contentVersion": "1.0.0.0",
        "triggers": {
            "When_a_HTTP_request_is_received": {
                "type": "Request",
                "kind": "Http",
                "inputs": {
                    "schema": {
                        "type": "object",
                        "properties": {
                            "deviceIds": {
                                "type": "array",
                                "items": {
                                    "type": "string"
                                }
                            },
                            "groupName": {
                                "type": "string"
                            }
                        },
                        "required": [
                            "deviceIds",
                            "groupName"
                        ]
                    }
                }
            }
        },
        "actions": {
            "HTTP_Check_Group": {
                "type": "Http",
                "inputs": {
                    "uri": "https://graph.microsoft.com/v1.0/groups?$filter=displayName eq '@{triggerBody()?['groupName']}'",
                    "method": "GET",
                    "authentication": {
                        "type": "ManagedServiceIdentity",
                        "audience": "https://graph.microsoft.com/"
                    }
                },
                "runAfter": {
                    "Response": [
                        "Succeeded"
                    ]
                },
                "runtimeConfiguration": {
                    "contentTransfer": {
                        "transferMode": "Chunked"
                    }
                }
            },
            "Group_Exists": {
                "type": "If",
                "expression": {
                    "and": [
                        {
                            "greater": [
                                "@length(body('HTTP_Check_Group')?['value'])",
                                0
                            ]
                        }
                    ]
                },
                "actions": {
                    "Set_GroupID_variable": {
                        "type": "SetVariable",
                        "inputs": {
                            "name": "GroupID",
                            "value": "body('HTTP_Check_Group')?['value'][0]['id']n"
                        }
                    },
                    "HTTP_Get_Group_Members": {
                        "type": "Http",
                        "inputs": {
                            "uri": "https://graph.microsoft.com/v1.0/groups/@{body('HTTP_Check_Group')?['value'][0]['id']}/members?$top=999&$select=id,displayName",
                            "method": "GET",
                            "authentication": {
                                "type": "ManagedServiceIdentity",
                                "audience": "https://graph.microsoft.com"
                            }
                        },
                        "runAfter": {
                            "Set_GroupID_variable": [
                                "Succeeded"
                            ]
                        },
                        "runtimeConfiguration": {
                            "contentTransfer": {
                                "transferMode": "Chunked"
                            },
                            "paginationPolicy": {
                                "minimumItemCount": 999
                            }
                        }
                    },
                    "For_each_member": {
                        "type": "Foreach",
                        "foreach": "@body('HTTP_Get_Group_Members')?['value']n",
                        "actions": {
                            "Append_members_array": {
                                "type": "AppendToArrayVariable",
                                "inputs": {
                                    "name": "allMembers",
                                    "value": "@json(concat('{"deviceId": "', item()?['Id'], '"}'))rn"
                                }
                            }
                        },
                        "runAfter": {
                            "HTTP_Get_Group_Members": [
                                "Succeeded"
                            ]
                        }
                    },
                    "View_Members_Arrary": {
                        "type": "Compose",
                        "inputs": "@variables('allMembers')",
                        "runAfter": {
                            "For_each_member": [
                                "Succeeded"
                            ]
                        }
                    }
                },
                "else": {
                    "actions": {
                        "HTTP_Create_Group": {
                            "type": "Http",
                            "inputs": {
                                "uri": "https://graph.microsoft.com/v1.0/groups",
                                "method": "POST",
                                "headers": {
                                    "Content-Type": "application/json"
                                },
                                "body": {
                                    "displayName": "@{triggerBody()?['groupName']}",
                                    "mailEnabled": false,
                                    "mailNickname": "@{replace(triggerBody()?['groupName'], ' ', '')}",
                                    "securityEnabled": true
                                },
                                "authentication": {
                                    "type": "ManagedServiceIdentity",
                                    "audience": "https://graph.microsoft.com/"
                                }
                            },
                            "runtimeConfiguration": {
                                "contentTransfer": {
                                    "transferMode": "Chunked"
                                }
                            }
                        },
                        "Get_New_GroupID": {
                            "type": "SetVariable",
                            "inputs": {
                                "name": "GroupID",
                                "value": "body('HTTP_Check_Group')?['value'][0]['id']n"
                            },
                            "runAfter": {
                                "HTTP_Create_Group": [
                                    "Succeeded"
                                ]
                            }
                        }
                    }
                },
                "runAfter": {
                    "Initialize_GroupID_variable": [
                        "Succeeded"
                    ],
                    "Initialize_allMembers_variable": [
                        "Succeeded"
                    ],
                    "Initialize_nextLink_Variable": [
                        "Succeeded"
                    ],
                    "Initialize_LoopDone_variable": [
                        "Succeeded"
                    ],
                    "Initialize_DeviceIDs_Array": [
                        "Succeeded"
                    ],
                    "HTTP_Check_Group": [
                        "Succeeded"
                    ]
                }
            },
            "Initialize_GroupID_variable": {
                "type": "InitializeVariable",
                "inputs": {
                    "variables": [
                        {
                            "name": "GroupID",
                            "type": "string"
                        }
                    ]
                },
                "runAfter": {
                    "HTTP_Check_Group": [
                        "Succeeded"
                    ]
                }
            },
            "Initialize_allMembers_variable": {
                "type": "InitializeVariable",
                "inputs": {
                    "variables": [
                        {
                            "name": "allMembers",
                            "type": "array"
                        }
                    ]
                },
                "runAfter": {
                    "HTTP_Check_Group": [
                        "Succeeded"
                    ]
                }
            },
            "Initialize_LoopDone_variable": {
                "type": "InitializeVariable",
                "inputs": {
                    "variables": [
                        {
                            "name": "LoopDone",
                            "type": "boolean",
                            "value": false
                        }
                    ]
                },
                "runAfter": {
                    "HTTP_Check_Group": [
                        "Succeeded"
                    ]
                }
            },
            "Initialize_nextLink_Variable": {
                "type": "InitializeVariable",
                "inputs": {
                    "variables": [
                        {
                            "name": "nextLink",
                            "type": "string"
                        }
                    ]
                },
                "runAfter": {
                    "HTTP_Check_Group": [
                        "Succeeded"
                    ]
                }
            },
            "View_the_POST_for_Troubleshooting": {
                "type": "Compose",
                "inputs": "@triggerBody()?['deviceIds']",
                "runAfter": {
                    "Response": [
                        "Succeeded"
                    ]
                }
            },
            "Initialize_DeviceIDs_Array": {
                "type": "InitializeVariable",
                "inputs": {
                    "variables": [
                        {
                            "name": "DeviceIds",
                            "type": "array",
                            "value": "@triggerBody()?['deviceIds']?['body']"
                        }
                    ]
                },
                "runAfter": {
                    "HTTP_Check_Group": [
                        "Succeeded"
                    ]
                }
            },
            "Response": {
                "type": "Response",
                "kind": "Http",
                "inputs": {
                    "statusCode": 200,
                    "body": "@triggerOutputs()?['body/deviceIds']rn"
                },
                "runAfter": {}
            },
            "Previous_Members": {
                "type": "If",
                "expression": {
                    "and": [
                        {
                            "not": {
                                "equals": [
                                    "@variables('allMembers')",
                                    "@null"
                                ]
                            }
                        }
                    ]
                },
                "actions": {
                    "Add_ObjectID": {
                        "type": "Foreach",
                        "foreach": "@outputs('Select_ObjectIds')['body']",
                        "actions": {
                            "Additions": {
                                "type": "If",
                                "expression": {
                                    "and": [
                                        {
                                            "contains": [
                                                "@variables('allMembers')",
                                                "@items('Add_ObjectID')"
                                            ]
                                        }
                                    ]
                                },
                                "actions": {},
                                "else": {
                                    "actions": {
                                        "Append_to_Additions": {
                                            "type": "AppendToArrayVariable",
                                            "inputs": {
                                                "name": "addIds",
                                                "value": "@items('Add_ObjectID')"
                                            }
                                        }
                                    }
                                }
                            }
                        },
                        "runAfter": {
                            "Remove_ObjectID": [
                                "Succeeded"
                            ]
                        }
                    },
                    "Remove_ObjectID": {
                        "type": "Foreach",
                        "foreach": "@outputs('Select_allMembers')['body']",
                        "actions": {
                            "Removals": {
                                "type": "If",
                                "expression": {
                                    "and": [
                                        {
                                            "contains": [
                                                "@body('Select_ObjectIds')",
                                                "@items('Remove_ObjectID')"
                                            ]
                                        }
                                    ]
                                },
                                "actions": {},
                                "else": {
                                    "actions": {
                                        "Append_to_Removals": {
                                            "type": "AppendToArrayVariable",
                                            "inputs": {
                                                "name": "removeIds",
                                                "value": "@items('Remove_ObjectID')"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "else": {
                    "actions": {
                        "Select_objectIds_Only": {
                            "type": "Select",
                            "inputs": {
                                "from": "@variables('ObjectIds')",
                                "select": {
                                    "DeviceId": "@item()?['DeviceId']"
                                }
                            }
                        },
                        "For_each_objectid": {
                            "type": "Foreach",
                            "foreach": "@variables('DeviceIds')",
                            "actions": {
                                "Append_to_Additions_Only": {
                                    "type": "AppendToArrayVariable",
                                    "inputs": {
                                        "name": "addIds",
                                        "value": "item()?['DeviceId']"
                                    }
                                }
                            },
                            "runAfter": {
                                "Select_objectIds_Only": [
                                    "Succeeded"
                                ]
                            }
                        }
                    }
                },
                "runAfter": {
                    "Select_ObjectIds": [
                        "Succeeded"
                    ]
                }
            },
            "Initialize_removeIds_Array": {
                "type": "InitializeVariable",
                "inputs": {
                    "variables": [
                        {
                            "name": "removeIds",
                            "type": "array"
                        }
                    ]
                },
                "runAfter": {
                    "Group_Exists": [
                        "Succeeded"
                    ],
                    "For_each_DeviceId_get_ObjectId": [
                        "Succeeded"
                    ]
                }
            },
            "Initialize_addIds_Array": {
                "type": "InitializeVariable",
                "inputs": {
                    "variables": [
                        {
                            "name": "addIds",
                            "type": "array"
                        }
                    ]
                },
                "runAfter": {
                    "Initialize_removeIds_Array": [
                        "Succeeded"
                    ],
                    "For_each_DeviceId_get_ObjectId": [
                        "Succeeded"
                    ]
                }
            },
            "Select_allMembers": {
                "type": "Select",
                "inputs": {
                    "from": "@variables('allMembers')",
                    "select": {
                        "DeviceId": "@item()?['deviceId']"
                    }
                },
                "runAfter": {
                    "Initialize_addIds_Array": [
                        "Succeeded"
                    ],
                    "For_each_DeviceId_get_ObjectId": [
                        "Succeeded"
                    ]
                }
            },
            "Select_ObjectIds": {
                "type": "Select",
                "inputs": {
                    "from": "@variables('ObjectIds')",
                    "select": {
                        "DeviceId": "@item()?['deviceId']"
                    }
                },
                "runAfter": {
                    "For_each_DeviceId_get_ObjectId": [
                        "Succeeded"
                    ],
                    "Select_allMembers": [
                        "Succeeded"
                    ]
                }
            },
            "View_Removals": {
                "type": "Compose",
                "inputs": "@variables('removeIds')",
                "runAfter": {
                    "Previous_Members": [
                        "Succeeded"
                    ]
                }
            },
            "View_Additions": {
                "type": "Compose",
                "inputs": "@variables('addIds')",
                "runAfter": {
                    "Previous_Members": [
                        "Succeeded"
                    ]
                }
            },
            "HTTP_Get_Final_Group_Members": {
                "type": "Http",
                "inputs": {
                    "uri": "https://graph.microsoft.com/v1.0/groups/@{body('HTTP_Check_Group')?['value'][0]['id']}/members?$top=999&$select=deviceId,displayName",
                    "method": "GET",
                    "authentication": {
                        "type": "ManagedServiceIdentity",
                        "audience": "https://graph.microsoft.com"
                    }
                },
                "runAfter": {
                    "If_removals": [
                        "Succeeded"
                    ],
                    "If_additions": [
                        "Succeeded"
                    ]
                },
                "runtimeConfiguration": {
                    "contentTransfer": {
                        "transferMode": "Chunked"
                    },
                    "paginationPolicy": {
                        "minimumItemCount": 500
                    }
                }
            },
            "For_each_DeviceId_get_ObjectId": {
                "type": "Foreach",
                "foreach": "@variables('DeviceIds')",
                "actions": {
                    "Get_ObjectIds": {
                        "type": "Http",
                        "inputs": {
                            "uri": "https://graph.microsoft.com/v1.0/devices?$filter=deviceId eq '@{item()?['deviceid']}'&$select=id,displayName",
                            "method": "GET",
                            "authentication": {
                                "type": "ManagedServiceIdentity",
                                "audience": "https://graph.microsoft.com"
                            }
                        },
                        "operationOptions": "DisableAsyncPattern",
                        "runtimeConfiguration": {
                            "contentTransfer": {
                                "transferMode": "Chunked"
                            }
                        }
                    },
                    "If_ObjectId_Found": {
                        "type": "If",
                        "expression": {
                            "and": [
                                {
                                    "equals": [
                                        "@outputs('Get_ObjectIds')?['statusCode']",
                                        200
                                    ]
                                },
                                {
                                    "greater": [
                                        "@outputs('Check_for_null_value')",
                                        0
                                    ]
                                }
                            ]
                        },
                        "actions": {
                            "Append_to_ObjectIds": {
                                "type": "AppendToArrayVariable",
                                "inputs": {
                                    "name": "ObjectIds",
                                    "value": {
                                        "DeviceId": "@{body('Get_ObjectIds')?['value'][0]['id']}",
                                        "DeviceName": "@{body('Get_ObjectIds')?['value'][0]['displayName']}"
                                    }
                                }
                            }
                        },
                        "else": {
                            "actions": {}
                        },
                        "runAfter": {
                            "Check_for_null_value": [
                                "Succeeded"
                            ]
                        }
                    },
                    "Check_for_null_value": {
                        "type": "Compose",
                        "inputs": "@length(body('Get_ObjectIds')?['value'])",
                        "runAfter": {
                            "Get_ObjectIds": [
                                "Succeeded",
                                "Failed"
                            ]
                        }
                    }
                },
                "runAfter": {
                    "Initialize_DeviceIDs_Array": [
                        "Succeeded"
                    ],
                    "Initialize_GroupID_variable": [
                        "Succeeded"
                    ],
                    "Initialize_allMembers_variable": [
                        "Succeeded"
                    ],
                    "Initialize_LoopDone_variable": [
                        "Succeeded"
                    ],
                    "Initialize_nextLink_Variable": [
                        "Succeeded"
                    ],
                    "Initialize_ObjectIds": [
                        "Succeeded"
                    ]
                }
            },
            "Initialize_ObjectIds": {
                "type": "InitializeVariable",
                "inputs": {
                    "variables": [
                        {
                            "name": "ObjectIds",
                            "type": "array"
                        }
                    ]
                },
                "runAfter": {
                    "HTTP_Check_Group": [
                        "Succeeded"
                    ]
                }
            },
            "If_removals": {
                "type": "If",
                "expression": {
                    "and": [
                        {
                            "greater": [
                                "@length(variables('removeIds'))",
                                0
                            ]
                        }
                    ]
                },
                "actions": {
                    "For_each_Removal": {
                        "type": "Foreach",
                        "foreach": "@variables('removeIds')",
                        "actions": {
                            "Remove_group_members": {
                                "type": "Http",
                                "inputs": {
                                    "uri": "https://graph.microsoft.com/v1.0/groups/@{body('HTTP_Check_Group')?['value'][0]['id']}/members/@{item()?['DeviceId']}/$ref",
                                    "method": "DELETE",
                                    "headers": {
                                        "Content-type": "application/json"
                                    },
                                    "authentication": {
                                        "type": "ManagedServiceIdentity",
                                        "audience": "https://graph.microsoft.com"
                                    }
                                },
                                "runtimeConfiguration": {
                                    "contentTransfer": {
                                        "transferMode": "Chunked"
                                    }
                                }
                            }
                        }
                    }
                },
                "else": {
                    "actions": {}
                },
                "runAfter": {
                    "View_Removals": [
                        "Succeeded"
                    ]
                }
            },
            "If_additions": {
                "type": "If",
                "expression": {
                    "and": [
                        {
                            "greater": [
                                "@length(variables('addIds'))",
                                0
                            ]
                        }
                    ]
                },
                "actions": {
                    "For_each_Addition": {
                        "type": "Foreach",
                        "foreach": "@variables('addIds')",
                        "actions": {
                            "Add_group_members": {
                                "type": "Http",
                                "inputs": {
                                    "uri": "https://graph.microsoft.com/v1.0/groups/@{body('HTTP_Check_Group')?['value'][0]['id']}/members/$ref",
                                    "method": "POST",
                                    "headers": {
                                        "Content-Type": "application/json"
                                    },
                                    "body": {
                                        "@@odata.id": "https://graph.microsoft.com/v1.0/devices/@{item()?['DeviceId']}"
                                    },
                                    "authentication": {
                                        "type": "ManagedServiceIdentity",
                                        "audience": "https://graph.microsoft.com"
                                    }
                                },
                                "runtimeConfiguration": {
                                    "contentTransfer": {
                                        "transferMode": "Chunked"
                                    }
                                }
                            }
                        }
                    }
                },
                "else": {
                    "actions": {}
                },
                "runAfter": {
                    "View_Additions": [
                        "Succeeded"
                    ]
                }
            },
            "Send_an_email_(V2)": {
                "type": "ApiConnection",
                "inputs": {
                    "host": {
                        "connection": {
                            "name": "@parameters('$connections')['office365']['connectionId']"
                        }
                    },
                    "method": "post",
                    "body": {
                        "To": "me@mydomain.com",
                        "Subject": "Group @{triggerBody()?['groupName']}has been updated",
                        "Body": "
The group @{triggerBody()?['groupName']}was updated. The group now includes these members:


@{body('Join_DeviceNames')}

",
                        "Importance": "Normal"
                    },
                    "path": "/v2/Mail"
                },
                "runAfter": {
                    "Join_DeviceNames": [
                        "Succeeded"
                    ]
                }
            },
            "Select_Final_members": {
                "type": "Select",
                "inputs": {
                    "from": "@body('HTTP_GET_Final_Group_Members')?['value']",
                    "select": {
                        "DeviceName:": "@item()?['displayName']"
                    }
                },
                "runAfter": {
                    "HTTP_Get_Final_Group_Members": [
                        "Succeeded"
                    ]
                }
            },
            "Join_DeviceNames": {
                "type": "Join",
                "inputs": {
                    "from": "@body('Select_Final_members')",
                    "joinWith": "@join(body('Select_Final_Members'), '\n')rn"
                },
                "runAfter": {
                    "Select_Final_members": [
                        "Succeeded"
                    ]
                }
            }
        },
        "outputs": {},
        "parameters": {
            "$connections": {
                "type": "Object",
                "defaultValue": {}
            }
        }
    },
    "parameters": {
        "$connections": {
            "value": {
                "office365": {
                    "id": "/subscriptions/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/providers/Microsoft.Web/locations/westus2/managedApis/office365",
                    "connectionId": "/subscriptions/XXXXXXXXXXXXXXXX/resourceGroups/Intune/providers/Microsoft.Web/connections/office365",
                    "connectionName": "office365"
                }
            }
        }
    }
		{
"definition": {
    "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
    "contentVersion": "1.0.0.0",
    "triggers": {
        "When_a_HTTP_request_is_received": {
            "type": "Request",
            "kind": "Http",
            "inputs": {
                "schema": {
                    "type": "object",
                    "properties": {
                        "deviceIds": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        },
                        "groupName": {
                            "type": "string"
                        }
                    },
                    "required": [
                        "deviceIds",
                        "groupName"
                    ]
                }
            }
        }
    },
    "actions": {
        "HTTP_Check_Group": {
            "type": "Http",
            "inputs": {
                "uri": "https://graph.microsoft.com/v1.0/groups?$filter=displayName eq '@{triggerBody()?['groupName']}'",
                "method": "GET",
                "authentication": {
                    "type": "ManagedServiceIdentity",
                    "audience": "https://graph.microsoft.com/"
                }
            },
            "runAfter": {
                "Response": [
                    "Succeeded"
                ]
            },
            "runtimeConfiguration": {
                "contentTransfer": {
                    "transferMode": "Chunked"
                }
            }
        },
        "Group_Exists": {
            "type": "If",
            "expression": {
                "and": [
                    {
                        "greater": [
                            "@length(body('HTTP_Check_Group')?['value'])",
                            0
                        ]
                    }
                ]
            },
            "actions": {
                "Set_GroupID_variable": {
                    "type": "SetVariable",
                    "inputs": {
                        "name": "GroupID",
                        "value": "body('HTTP_Check_Group')?['value'][0]['id']n"
                    }
                },
                "HTTP_Get_Group_Members": {
                    "type": "Http",
                    "inputs": {
                        "uri": "https://graph.microsoft.com/v1.0/groups/@{body('HTTP_Check_Group')?['value'][0]['id']}/members?$top=999&$select=id,displayName",
                        "method": "GET",
                        "authentication": {
                            "type": "ManagedServiceIdentity",
                            "audience": "https://graph.microsoft.com"
                        }
                    },
                    "runAfter": {
                        "Set_GroupID_variable": [
                            "Succeeded"
                        ]
                    },
                    "runtimeConfiguration": {
                        "contentTransfer": {
                            "transferMode": "Chunked"
                        },
                        "paginationPolicy": {
                            "minimumItemCount": 999
                        }
                    }
                },
                "For_each_member": {
                    "type": "Foreach",
                    "foreach": "@body('HTTP_Get_Group_Members')?['value']n",
                    "actions": {
                        "Append_members_array": {
                            "type": "AppendToArrayVariable",
                            "inputs": {
                                "name": "allMembers",
                                "value": "@json(concat('{"deviceId": "', item()?['Id'], '"}'))rn"
                            }
                        }
                    },
                    "runAfter": {
                        "HTTP_Get_Group_Members": [
                            "Succeeded"
                        ]
                    }
                },
                "View_Members_Arrary": {
                    "type": "Compose",
                    "inputs": "@variables('allMembers')",
                    "runAfter": {
                        "For_each_member": [
                            "Succeeded"
                        ]
                    }
                }
            },
            "else": {
                "actions": {
                    "HTTP_Create_Group": {
                        "type": "Http",
                        "inputs": {
                            "uri": "https://graph.microsoft.com/v1.0/groups",
                            "method": "POST",
                            "headers": {
                                "Content-Type": "application/json"
                            },
                            "body": {
                                "displayName": "@{triggerBody()?['groupName']}",
                                "mailEnabled": false,
                                "mailNickname": "@{replace(triggerBody()?['groupName'], ' ', '')}",
                                "securityEnabled": true
                            },
                            "authentication": {
                                "type": "ManagedServiceIdentity",
                                "audience": "https://graph.microsoft.com/"
                            }
                        },
                        "runtimeConfiguration": {
                            "contentTransfer": {
                                "transferMode": "Chunked"
                            }
                        }
                    },
                    "Get_New_GroupID": {
                        "type": "SetVariable",
                        "inputs": {
                            "name": "GroupID",
                            "value": "body('HTTP_Check_Group')?['value'][0]['id']n"
                        },
                        "runAfter": {
                            "HTTP_Create_Group": [
                                "Succeeded"
                            ]
                        }
                    }
                }
            },
            "runAfter": {
                "Initialize_GroupID_variable": [
                    "Succeeded"
                ],
                "Initialize_allMembers_variable": [
                    "Succeeded"
                ],
                "Initialize_nextLink_Variable": [
                    "Succeeded"
                ],
                "Initialize_LoopDone_variable": [
                    "Succeeded"
                ],
                "Initialize_DeviceIDs_Array": [
                    "Succeeded"
                ],
                "HTTP_Check_Group": [
                    "Succeeded"
                ]
            }
        },
        "Initialize_GroupID_variable": {
            "type": "InitializeVariable",
            "inputs": {
                "variables": [
                    {
                        "name": "GroupID",
                        "type": "string"
                    }
                ]
            },
            "runAfter": {
                "HTTP_Check_Group": [
                    "Succeeded"
                ]
            }
        },
        "Initialize_allMembers_variable": {
            "type": "InitializeVariable",
            "inputs": {
                "variables": [
                    {
                        "name": "allMembers",
                        "type": "array"
                    }
                ]
            },
            "runAfter": {
                "HTTP_Check_Group": [
                    "Succeeded"
                ]
            }
        },
        "Initialize_LoopDone_variable": {
            "type": "InitializeVariable",
            "inputs": {
                "variables": [
                    {
                        "name": "LoopDone",
                        "type": "boolean",
                        "value": false
                    }
                ]
            },
            "runAfter": {
                "HTTP_Check_Group": [
                    "Succeeded"
                ]
            }
        },
        "Initialize_nextLink_Variable": {
            "type": "InitializeVariable",
            "inputs": {
                "variables": [
                    {
                        "name": "nextLink",
                        "type": "string"
                    }
                ]
            },
            "runAfter": {
                "HTTP_Check_Group": [
                    "Succeeded"
                ]
            }
        },
        "View_the_POST_for_Troubleshooting": {
            "type": "Compose",
            "inputs": "@triggerBody()?['deviceIds']",
            "runAfter": {
                "Response": [
                    "Succeeded"
                ]
            }
        },
        "Initialize_DeviceIDs_Array": {
            "type": "InitializeVariable",
            "inputs": {
                "variables": [
                    {
                        "name": "DeviceIds",
                        "type": "array",
                        "value": "@triggerBody()?['deviceIds']?['body']"
                    }
                ]
            },
            "runAfter": {
                "HTTP_Check_Group": [
                    "Succeeded"
                ]
            }
        },
        "Response": {
            "type": "Response",
            "kind": "Http",
            "inputs": {
                "statusCode": 200,
                "body": "@triggerOutputs()?['body/deviceIds']rn"
            },
            "runAfter": {}
        },
        "Previous_Members": {
            "type": "If",
            "expression": {
                "and": [
                    {
                        "not": {
                            "equals": [
                                "@variables('allMembers')",
                                "@null"
                            ]
                        }
                    }
                ]
            },
            "actions": {
                "Add_ObjectID": {
                    "type": "Foreach",
                    "foreach": "@outputs('Select_ObjectIds')['body']",
                    "actions": {
                        "Additions": {
                            "type": "If",
                            "expression": {
                                "and": [
                                    {
                                        "contains": [
                                            "@variables('allMembers')",
                                            "@items('Add_ObjectID')"
                                        ]
                                    }
                                ]
                            },
                            "actions": {},
                            "else": {
                                "actions": {
                                    "Append_to_Additions": {
                                        "type": "AppendToArrayVariable",
                                        "inputs": {
                                            "name": "addIds",
                                            "value": "@items('Add_ObjectID')"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "runAfter": {
                        "Remove_ObjectID": [
                            "Succeeded"
                        ]
                    }
                },
                "Remove_ObjectID": {
                    "type": "Foreach",
                    "foreach": "@outputs('Select_allMembers')['body']",
                    "actions": {
                        "Removals": {
                            "type": "If",
                            "expression": {
                                "and": [
                                    {
                                        "contains": [
                                            "@body('Select_ObjectIds')",
                                            "@items('Remove_ObjectID')"
                                        ]
                                    }
                                ]
                            },
                            "actions": {},
                            "else": {
                                "actions": {
                                    "Append_to_Removals": {
                                        "type": "AppendToArrayVariable",
                                        "inputs": {
                                            "name": "removeIds",
                                            "value": "@items('Remove_ObjectID')"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "else": {
                "actions": {
                    "Select_objectIds_Only": {
                        "type": "Select",
                        "inputs": {
                            "from": "@variables('ObjectIds')",
                            "select": {
                                "DeviceId": "@item()?['DeviceId']"
                            }
                        }
                    },
                    "For_each_objectid": {
                        "type": "Foreach",
                        "foreach": "@variables('DeviceIds')",
                        "actions": {
                            "Append_to_Additions_Only": {
                                "type": "AppendToArrayVariable",
                                "inputs": {
                                    "name": "addIds",
                                    "value": "item()?['DeviceId']"
                                }
                            }
                        },
                        "runAfter": {
                            "Select_objectIds_Only": [
                                "Succeeded"
                            ]
                        }
                    }
                }
            },
            "runAfter": {
                "Select_ObjectIds": [
                    "Succeeded"
                ]
            }
        },
        "Initialize_removeIds_Array": {
            "type": "InitializeVariable",
            "inputs": {
                "variables": [
                    {
                        "name": "removeIds",
                        "type": "array"
                    }
                ]
            },
            "runAfter": {
                "Group_Exists": [
                    "Succeeded"
                ],
                "For_each_DeviceId_get_ObjectId": [
                    "Succeeded"
                ]
            }
        },
        "Initialize_addIds_Array": {
            "type": "InitializeVariable",
            "inputs": {
                "variables": [
                    {
                        "name": "addIds",
                        "type": "array"
                    }
                ]
            },
            "runAfter": {
                "Initialize_removeIds_Array": [
                    "Succeeded"
                ],
                "For_each_DeviceId_get_ObjectId": [
                    "Succeeded"
                ]
            }
        },
        "Select_allMembers": {
            "type": "Select",
            "inputs": {
                "from": "@variables('allMembers')",
                "select": {
                    "DeviceId": "@item()?['deviceId']"
                }
            },
            "runAfter": {
                "Initialize_addIds_Array": [
                    "Succeeded"
                ],
                "For_each_DeviceId_get_ObjectId": [
                    "Succeeded"
                ]
            }
        },
        "Select_ObjectIds": {
            "type": "Select",
            "inputs": {
                "from": "@variables('ObjectIds')",
                "select": {
                    "DeviceId": "@item()?['deviceId']"
                }
            },
            "runAfter": {
                "For_each_DeviceId_get_ObjectId": [
                    "Succeeded"
                ],
                "Select_allMembers": [
                    "Succeeded"
                ]
            }
        },
        "View_Removals": {
            "type": "Compose",
            "inputs": "@variables('removeIds')",
            "runAfter": {
                "Previous_Members": [
                    "Succeeded"
                ]
            }
        },
        "View_Additions": {
            "type": "Compose",
            "inputs": "@variables('addIds')",
            "runAfter": {
                "Previous_Members": [
                    "Succeeded"
                ]
            }
        },
        "HTTP_Get_Final_Group_Members": {
            "type": "Http",
            "inputs": {
                "uri": "https://graph.microsoft.com/v1.0/groups/@{body('HTTP_Check_Group')?['value'][0]['id']}/members?$top=999&$select=deviceId,displayName",
                "method": "GET",
                "authentication": {
                    "type": "ManagedServiceIdentity",
                    "audience": "https://graph.microsoft.com"
                }
            },
            "runAfter": {
                "If_removals": [
                    "Succeeded"
                ],
                "If_additions": [
                    "Succeeded"
                ]
            },
            "runtimeConfiguration": {
                "contentTransfer": {
                    "transferMode": "Chunked"
                },
                "paginationPolicy": {
                    "minimumItemCount": 500
                }
            }
        },
        "For_each_DeviceId_get_ObjectId": {
            "type": "Foreach",
            "foreach": "@variables('DeviceIds')",
            "actions": {
                "Get_ObjectIds": {
                    "type": "Http",
                    "inputs": {
                        "uri": "https://graph.microsoft.com/v1.0/devices?$filter=deviceId eq '@{item()?['deviceid']}'&$select=id,displayName",
                        "method": "GET",
                        "authentication": {
                            "type": "ManagedServiceIdentity",
                            "audience": "https://graph.microsoft.com"
                        }
                    },
                    "operationOptions": "DisableAsyncPattern",
                    "runtimeConfiguration": {
                        "contentTransfer": {
                            "transferMode": "Chunked"
                        }
                    }
                },
                "If_ObjectId_Found": {
                    "type": "If",
                    "expression": {
                        "and": [
                            {
                                "equals": [
                                    "@outputs('Get_ObjectIds')?['statusCode']",
                                    200
                                ]
                            },
                            {
                                "greater": [
                                    "@outputs('Check_for_null_value')",
                                    0
                                ]
                            }
                        ]
                    },
                    "actions": {
                        "Append_to_ObjectIds": {
                            "type": "AppendToArrayVariable",
                            "inputs": {
                                "name": "ObjectIds",
                                "value": {
                                    "DeviceId": "@{body('Get_ObjectIds')?['value'][0]['id']}",
                                    "DeviceName": "@{body('Get_ObjectIds')?['value'][0]['displayName']}"
                                }
                            }
                        }
                    },
                    "else": {
                        "actions": {}
                    },
                    "runAfter": {
                        "Check_for_null_value": [
                            "Succeeded"
                        ]
                    }
                },
                "Check_for_null_value": {
                    "type": "Compose",
                    "inputs": "@length(body('Get_ObjectIds')?['value'])",
                    "runAfter": {
                        "Get_ObjectIds": [
                            "Succeeded",
                            "Failed"
                        ]
                    }
                }
            },
            "runAfter": {
                "Initialize_DeviceIDs_Array": [
                    "Succeeded"
                ],
                "Initialize_GroupID_variable": [
                    "Succeeded"
                ],
                "Initialize_allMembers_variable": [
                    "Succeeded"
                ],
                "Initialize_LoopDone_variable": [
                    "Succeeded"
                ],
                "Initialize_nextLink_Variable": [
                    "Succeeded"
                ],
                "Initialize_ObjectIds": [
                    "Succeeded"
                ]
            }
        },
        "Initialize_ObjectIds": {
            "type": "InitializeVariable",
            "inputs": {
                "variables": [
                    {
                        "name": "ObjectIds",
                        "type": "array"
                    }
                ]
            },
            "runAfter": {
                "HTTP_Check_Group": [
                    "Succeeded"
                ]
            }
        },
        "If_removals": {
            "type": "If",
            "expression": {
                "and": [
                    {
                        "greater": [
                            "@length(variables('removeIds'))",
                            0
                        ]
                    }
                ]
            },
            "actions": {
                "For_each_Removal": {
                    "type": "Foreach",
                    "foreach": "@variables('removeIds')",
                    "actions": {
                        "Remove_group_members": {
                            "type": "Http",
                            "inputs": {
                                "uri": "https://graph.microsoft.com/v1.0/groups/@{body('HTTP_Check_Group')?['value'][0]['id']}/members/@{item()?['DeviceId']}/$ref",
                                "method": "DELETE",
                                "headers": {
                                    "Content-type": "application/json"
                                },
                                "authentication": {
                                    "type": "ManagedServiceIdentity",
                                    "audience": "https://graph.microsoft.com"
                                }
                            },
                            "runtimeConfiguration": {
                                "contentTransfer": {
                                    "transferMode": "Chunked"
                                }
                            }
                        }
                    }
                }
            },
            "else": {
                "actions": {}
            },
            "runAfter": {
                "View_Removals": [
                    "Succeeded"
                ]
            }
        },
        "If_additions": {
            "type": "If",
            "expression": {
                "and": [
                    {
                        "greater": [
                            "@length(variables('addIds'))",
                            0
                        ]
                    }
                ]
            },
            "actions": {
                "For_each_Addition": {
                    "type": "Foreach",
                    "foreach": "@variables('addIds')",
                    "actions": {
                        "Add_group_members": {
                            "type": "Http",
                            "inputs": {
                                "uri": "https://graph.microsoft.com/v1.0/groups/@{body('HTTP_Check_Group')?['value'][0]['id']}/members/$ref",
                                "method": "POST",
                                "headers": {
                                    "Content-Type": "application/json"
                                },
                                "body": {
                                    "@@odata.id": "https://graph.microsoft.com/v1.0/devices/@{item()?['DeviceId']}"
                                },
                                "authentication": {
                                    "type": "ManagedServiceIdentity",
                                    "audience": "https://graph.microsoft.com"
                                }
                            },
                            "runtimeConfiguration": {
                                "contentTransfer": {
                                    "transferMode": "Chunked"
                                }
                            }
                        }
                    }
                }
            },
            "else": {
                "actions": {}
            },
            "runAfter": {
                "View_Additions": [
                    "Succeeded"
                ]
            }
        },
        "Send_an_email_(V2)": {
            "type": "ApiConnection",
            "inputs": {
                "host": {
                    "connection": {
                        "name": "@parameters('$connections')['office365']['connectionId']"
                    }
                },
                "method": "post",
                "body": {
                    "To": "me@mydomain.com",
                    "Subject": "Group @{triggerBody()?['groupName']}has been updated",
                    "Body": "<p class="editor-paragraph">The group @{triggerBody()?['groupName']}was updated. The group now includes these members:</p><br><p class="editor-paragraph">@{body('Join_DeviceNames')}</p><br>",
                    "Importance": "Normal"
                },
                "path": "/v2/Mail"
            },
            "runAfter": {
                "Join_DeviceNames": [
                    "Succeeded"
                ]
            }
        },
        "Select_Final_members": {
            "type": "Select",
            "inputs": {
                "from": "@body('HTTP_GET_Final_Group_Members')?['value']",
                "select": {
                    "DeviceName:": "@item()?['displayName']"
                }
            },
            "runAfter": {
                "HTTP_Get_Final_Group_Members": [
                    "Succeeded"
                ]
            }
        },
        "Join_DeviceNames": {
            "type": "Join",
            "inputs": {
                "from": "@body('Select_Final_members')",
                "joinWith": "@join(body('Select_Final_Members'), '\n')rn"
            },
            "runAfter": {
                "Select_Final_members": [
                    "Succeeded"
                ]
            }
        }
    },
    "outputs": {},
    "parameters": {
        "$connections": {
            "type": "Object",
            "defaultValue": {}
        }
    }
},
"parameters": {
    "$connections": {
        "value": {
            "office365": {
                "id": "/subscriptions/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/providers/Microsoft.Web/locations/westus2/managedApis/office365",
                "connectionId": "/subscriptions/XXXXXXXXXXXXXXXX/resourceGroups/Intune/providers/Microsoft.Web/connections/office365",
                "connectionName": "office365"
            }
        }
    }
}

Final Thoughts

This approach is a workaround, but it allows us to mimic ConfigMgr’s dynamic collections in Intune. For those who desire a more ConfigMgr like method of grouping assets, this method can significantly improve targeting and flexibility when managing devices with Intune.

PowerStacks customers can reach out for help implementing this solution. For others, I hope this guide sparks ideas for customizing Intune to better meet your organization’s needs.


Want deeper insights into your Intune device groups? BI for Intune provides pre-built Power BI dashboards for device inventory, compliance, software updates, and more — giving you the reporting capabilities that Intune’s built-in tools lack. Start a free trial →

BlogIntune