Close Menu
Peter Klapwijk – In The Cloud 24-7Peter Klapwijk – In The Cloud 24-7
    Facebook X (Twitter) Instagram
    Peter Klapwijk – In The Cloud 24-7Peter Klapwijk – In The Cloud 24-7
    • Home
    • Intune
    • Windows
      • Modern Workplace
    • macOS
    • Android
    • iOS
    • Automation
      • Logic Apps
      • Intune Monitoring
      • GitHub
    • Security
      • Passwordless
      • Security
    • Speaking
    • About me
    Peter Klapwijk – In The Cloud 24-7Peter Klapwijk – In The Cloud 24-7
    Home»Automation»Intune RBAC – Create country based device groups with Logic Apps
    Automation

    Intune RBAC – Create country based device groups with Logic Apps

    Peter KlapwijkBy Peter KlapwijkMarch 24, 2022Updated:February 14, 202539 Mins Read

    A lot of companies have business in different countries, with a local IT department that needs to manage the Intune managed devices of their specific country. In Intune, it is possible to scope permissions to a certain group of devices using scope tags. These scope tags can be assigned to devices, based on membership of an Azure AD (AAD) group. For Windows devices, for which a naming convention per country can be used via Windows Autopilot or Group TAGs can be assigned per country, membership can be easily done with a dynamic AAD group. But for Android and iOS devices this is more complicated.

    In this blog post, I show you how we can create country bases devices groups, by using a Logic Apps flow.

    The solution

    For this solution, we need to have AAD user groups per country. With Graph API we retrieve all the managed Android and iOS devices. In the flow, we determine who the primary user of a device is. We take that primary user and determine which AAD user group the primary user is a member of. With this information, we are able to add the device to an AAD Device group. I used two device groups per country, one for Android and one for iOS, you might create just one device group per country.

    To make the flow not too complicated and make it easily possible to expand the countries with their AAD groups, I use a SharePoint List where I store the object IDs from the AAD Device groups.

    This is what the complete flow looks like.

    The flow is available on my GitHub repository as an ARM template. The Bicep deployment files will follow soon.

    The requirements

    To get this Logic Apps flow up and running we have a few requirements.

    I previously used an Azure App Registration to authenticate to Graph and set the permissions. But I recently learned it is easier and safer to use an Azure Managed Identity for this. So the first requirement is an Azure Managed Identity.

    These permissions need to be assigned to the Managed Identity:
    Device.Read.All
    DeviceManagementManagedDevices.Read.All
    GroupMember.ReadWrite.All
    User.Read.All

    We need an AAD User group per country (or business unit) and an AAD Device group per country (or like I use, one group per country for Android and one per country for iOS).

    And we need to create a SharePoint List, to which a (service) account has read permission to grab the information we need from the list.
    I created the List like the below example. The Name columns are just there for easy reference to which ObjectID belongs to which AAD group. The names of the columns which hold a Group ObjectId, need to match the query in the SharePoint action (which we later in the post add in the Logic Apps flow). Otherwise, the flow won’t add devices to the device groups.

    Setup the Logic Apps flow

    Let’s configure the Logic Apps flow! I start with the part of the flow which retrieves all the Android devices and processes these.

    Sign in to the Azure portal and open the Logic App service. I created a blank Logic App of type Consumption.

    When the flow is created, click on the name of the flow at the top of the screen, open the Identity section, and on the tab User assigned add your Managed Identity.

    Open the Overview tab, which shows a few templates, choose Recurrence.

    The Logic App designer is opened and the recurrence trigger is added. Choose the recurrence settings of your choice; once a day, once an hour.

    First, we are going to add an Initialize variable action to the flow, which is found as (built-in) variables action. In this initialize variable, we store the object IDs of our AAD user groups.
    Enter a Name and choose Object as type.
    Enter the object IDs in this format (replace these with your own object IDs):

    {
      "groupIds": [
        "000000-000e-0ac1-a0ec-0ad80f0f0d0",
        "111111-1a11-1fcd-b11d-11d11bfdf111"
      ]
    }

    The next step we’re going to add is an HTTP Action, to query Intune via Graph for all managed Android devices.

    Choose GET as Method.
    As URI enter:

    https://graph.microsoft.com/beta/deviceManagement/managedDevices?$filter=((((deviceType%20eq%20'android')%20or%20(deviceType%20eq%20'androidForWork')%20or%20(deviceType%20eq%20'androidnGMS'))%20or%20((deviceType%20eq%20'androidEnterprise')%20and%20((deviceEnrollmentType%20eq%20'androidEnterpriseDedicatedDevice')%20or%20(deviceEnrollmentType%20eq%20'androidEnterpriseFullyManaged')%20or%20(deviceEnrollmentType%20eq%20'androidEnterpriseCorporateWorkProfile')))))

    Choose Add new parameter and check Authentication. Select Managed Identity as authentication type. Choose the previously added Managed Identity and enter https://graph.microsoft.com as Audience.

    To use the information we received (by executing this HTTP action) in the upcoming actions, we need to parse the received information with a Parse JSON action.
    As Content, we add the Body from the HTTP action, which is found as Dynamic content.



    To fill the schema with the correct information, we can add an example payload. The information to use as an example payload can be ‘generated’ by running the flow. Save the flow and hit Run trigger to start the flow.

    Open the Runs history from the flow and open the HTTP action. Copy the body.

    Another approach is to run the query via Graph Explorer and copy the information from the response.

    Back in de designer, click Use sample payload in the Parse JSON action, past the information which we copied from the runs history (or Graph explorer) in the new pop-up, and click Done.

    We’re adding a second HTTP action. In the previous HTTP action we retrieved the Azure AD Device ID from every device, but to add the device to a group, we need to have the object ID of the device, which we retrieve with this action.

    Choose GET as Method.
    As URI enter:

    https://graph.microsoft.com/v1.0/devices?$filter=(deviceId eq '[azureADDeviceId]')&$select=id,deviceId,displayName

    Replace [azureADDeviceId] with the azureADDeviceId Dynamic content from the Parse JSON action.

    The HTTP Action is automatically added to a For each action.
    Further, select the authentication method and audience like in the previous HTTP action.

    Again we add a Parse JSON action to our flow.

    This is the schema when you used the same select values as I did:

    {
        "properties": {
            "@@odata.context": {
                "type": "string"
            },
            "value": {
                "items": {
                    "properties": {
                        "deviceId": {
                            "type": "string"
                        },
                        "displayName": {
                            "type": "string"
                        },
                        "id": {
                            "type": "string"
                        }
                    },
                    "required": [
                        "id",
                        "deviceId",
                        "displayName"
                    ],
                    "type": "object"
                },
                "type": "array"
            }
        },
        "type": "object"
    }

    The next step is to add a Condition to the flow, which is a Control action.
    With this action, we filter out devices that don’t have a primary user set and thus for which we are not able to determine from which country these are.

    Search for userPrincipalName as Dynamic content, which is a value from the first Parse JSON Action, and add it in the left text box.

    Select is not equal to, from the drop-down list and leave the right text box empty.
    This is our Condition action.

    False we leave empty as we don’t have a UPN, we can’t move on with the flow.
    Under True, we add an HTTP Action.

    Choose POST as Method.
    As URI enter:

    https://graph.microsoft.com/v1.0/users/[UPN]/checkMemberGroups

    Replace [UPN] with userPrincipalName as Dynamic content, which is a value from the first Parse JSON Action.

    In the Body field, we add the UserGroupIDs (from the initialize variable action).
    Further, select the authentication method and audience like in the previous HTTP action.

    Add a Parse JSON action.
    This is the schema you can use.

    {
        "properties": {
            "@@odata.context": {
                "type": "string"
            },
            "value": {
                "items": {
                    "type": "string"
                },
                "type": "array"
            }
        },
        "type": "object"
    }

    We are going to add a SharePoint action, which is the Get Items action. With this action, we retrieve the information we stored in the SharePoint List, by using the group we retrieved in the previous action.

    Click Sign in to sign in with the (service) account.

    Choose the Site Address and List name from the drop-down list (or enter it as a custom value).
    Click Add a new parameter and choose Filter query.
    As query add:

    UserGroupObjectID eq '[item]'

    Replace [item] with the Item, which can be found as Dynamic content from the last Parse JSON action. This adds the SharePoint action in a For each.

    Next, we’re adding an HTTP action. With this action, we check if the device is already a member of the device group. If we don’t first check the membership, but just try to add the device to the group and it is already a member, our flow will end with a failure.

    Choose GET as Method.
    As URI enter:

    https://graph.microsoft.com/v1.0/devices/[id]/memberOf/[AndroidDeviceGroupObjectID]

    Replaced [id] with the Id of the Parse JSON Get AADDevice Android action.

    And replace [AndroidDeviceGroupObjectID] with the AndroidDeviceGroupObjectID of the SharePoint Get items action.
    These steps will automatically add the HTTP action in two For each actions.
    Further, select the authentication method and audience like in the previous HTTP action.

    When the device is not yet a member of the group, the previous HTTP action will fail with a status code 404. We use that status code in a Condition action, to end our flow when the device is already a member of the group, or to move on with the flow and add the device to a group.

    Add a Condition action.
    In the left text box add Status code from the previous HTTP action.
    Choose is equal to from the drop-down list. Enter 404 in the right text box.

    We need to make sure this condition action runs even when the HTTP action fails. For this, click on the three dots to open the settings of the condition, choose Configure run after. Select has failed and click Done.

    For this part of the flow, add the last HTTP action under True.

    Choose POST as Method.
    As URI enter:

    https://graph.microsoft.com/v1.0/groups/[AndroidDeviceGroupObjectID]/members/$ref

    Replace [AndroidDeviceGroupObjectID] with the AndroidDeviceGroupObjectID of the SharePoint Get items action.

    In the Body field enter:

    {
      "@@odata.id": "https://graph.microsoft.com/v1.0/devices/[id]"
    }

    Replace [id] with the id of the Parse JSON Get AADDevice Android action.

    Further, select the authentication method and audience like in the previous HTTP action.

    This is what our current flow looks like.

    Depending on your needs, you can create a second flow with the same steps to retrieve all iOS devices. Or we can create a parallel branch in the same flow to retrieve and process the iOS devices.

    If the choice is a parallel branch, click the plus button between the initialize variable and first HTTP action.

    And add an HTTP Action in the new branch.

    The URI to retrieve all iOS devices for the new action is:

    https://graph.microsoft.com/beta/deviceManagement/managedDevices?$filter=(((deviceType%20eq%20'iPad')%20or%20(deviceType%20eq%20'iPhone')%20or%20(deviceType%20eq%20'iPod')))

    Add all the steps which we added for Android, also for the iOS devices. If you finished creating the whole flow, for Android and iOS, it looks like this one.

    That’s it. We now have our device groups filled with devices. Based on these groups we can assign scope tags in Intune and provide local IT with the required permissions for their countries devices.

    Thanks for reading!

    Intune Logic Apps MEM Microsoft Endpoint Manager Power Automate
    Share. Facebook Twitter LinkedIn Email WhatsApp
    Peter Klapwijk
    • Website
    • X (Twitter)
    • LinkedIn

    Peter is a Security (Intune) MVP since 2020 and is working as Modern Workplace Engineer at Wortell in The Netherlands. He has more than 15 years of experience in IT, with a strong focus on Microsoft technologies like Microsoft Intune, Windows, and (low-code) automation.

    Related Posts

    Assign Deny Local Log On user right to an (Azure) AD group by using Microsoft Intune

    June 1, 2022

    Create an application-based Azure AD group with Logic Apps

    May 9, 2022

    Export Endpoint Analytics Proactive remediation data with Logic Apps

    April 19, 2021
    View 3 Comments

    3 Comments

    1. Casey Throop on August 3, 2022 04:21

      Hey Peter,

      Thanks so much for this guide! It’s helped me solve another problem we were having around device grouping based on user dept. I’ve got it working now, the only remaining struggle I have is the logic app status reports as failed. It will show failed if the device is already in the group or if the primary user no longer exists(this is a process thing for my team).
      I was looking at adding a condition to filter out the failed tasks so it would show success if devices were already a member of the group but if I put a condition after checkmembergroups http call it will fail.

      If you have any insight into where I could look or what I might be able to implement to help mitigate these false positives that would be amazing!

      Thanks again and great post!!

      Reply
    2. Enric Díaz on April 11, 2023 16:06

      Hi Peter,

      It was a very useful guide. Thank you so much for dedicating time for doing this.

      I wanted to add an additional step that is required just before making the first call to the “HTTP Get Android Devices” and is that if your tenant has more than a 1000 devices the first Get will only get the first 1000.

      To solve this I have made a Do-While, declaring a variable before with URI + filters for the first 1000 devices, and then in the get URI putting the variable on it. The same query replies with an attribute called “@odata.nextLink” with the new URI for the next 1000 devices.

      Reply
    3. Enric Díaz on April 19, 2023 16:02

      Hi Peter,

      I had one question regarding this flow. Why is the SharePoint List access not at the beginning? With that change you can optimize and only change the groups on the Sharepoint List without accessing the flow to change the declared variable.

      Thank you

      Reply
    Leave A Reply Cancel Reply

    Peter Klapwijk

    Hi! Welcome to my blog post.
    I hope you enjoy reading my articles.

    Hit the About Me button to get in contact with me or leave a comment.

    Awards
    Sponsor
    Latest Posts

    Hide the “Turn on an ad privacy feature” pop-up in Chrome with Microsoft Intune

    April 19, 2025

    How to set Google as default search provider with Microsoft Intune

    April 18, 2025

    Using Windows Autopilot device preparation with Windows 365 Frontline shared cloud PCs

    April 13, 2025

    Using Visual Studio with Microsoft Endpoint Privilege Management, some notes

    April 8, 2025
    follow me
    • Twitter 4.8K
    • LinkedIn 6.1K
    • YouTube
    Tags
    Administrative Templates Android Automation Autopilot Azure Azure AD Browser Conditional Access Edge EMS Exchange Online Feitian FIDO2 Flow Google Chrome Graph Graph API Identity Management Intune Intune Monitoring iOS KIOSK Logic Apps macOS MEM MEMMonitoring Microsoft 365 Microsoft Edge Microsoft Endpoint Manager Modern Workplace Office 365 OneDrive for Business Outlook Passwordless PowerApps Power Automate Security SharePoint Online Teams Windows Windows 10 Windows10 Windows 11 Windows Autopilot Windows Update
    Copy right

    This information is provided “AS IS” with no warranties, confers no rights and is not supported by the authors, or In The Cloud 24-7.

     

    Copyright © 2025 by In The Cloud 24-7/ Peter Klapwijk. All rights reserved, No part of the information on this web site may be reproduced or posted in any form or by any means without the prior written permission of the publisher.

    Shorthand; Don’t pass off my work as yours, it’s not nice.

    Recent Comments
    • Peter Klapwijk on Using Windows Autopilot device preparation with Windows 365 Frontline shared cloud PCs
    • John M on Using Windows Autopilot device preparation with Windows 365 Frontline shared cloud PCs
    • Christoffer Jakobsen on Connect to Azure file shares with Microsoft Entra Private Access
    • Ludo on How to block Bluetooth file transfer with Microsoft Intune
    • RCharles on Automatically configure the time zone (during Autopilot enrollment)
    most popular

    Application installation issues; Download pending

    October 1, 2024

    Restrict which users can logon into a Windows 10 device with Microsoft Intune

    April 11, 2020

    How to change the Windows 11 language with Intune

    November 11, 2022

    Update Microsoft Edge during Windows Autopilot enrollments

    July 9, 2024
    Peter Klapwijk – In The Cloud 24-7
    X (Twitter) LinkedIn YouTube RSS
    © 2025 ThemeSphere. Designed by ThemeSphere.

    Type above and press Enter to search. Press Esc to cancel.

    Manage Cookie Consent
    To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
    Functional Always active
    The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
    Preferences
    The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
    Statistics
    The technical storage or access that is used exclusively for statistical purposes. The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
    Marketing
    The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.
    Manage options Manage services Manage {vendor_count} vendors Read more about these purposes
    View preferences
    {title} {title} {title}