Introducing a simple remote device manager app for Microsoft Intune

This new year starts with something completely new. That means, some technology that hasn’t been part of any of the posts on my blog before. Inspired by some posts of Courtenay Bernier, I took some time to dive into the world of Microsoft Power Apps and Microsoft Power Automate, in combination with Microsoft Intune (and Microsoft Graph). This post will cover how I’ve used those technologies – with almost no custom code – to create a simple remote device manager app for Microsoft Intune. I’ll also hope that this post will show the power of this combination and inspire more readers to dive into that world. Basic knowledge of the mentioned technologies is required, as this post won’t be completely step-by-step and won’t provide a downloadable example.

That idea of the remote device manager app is to provide the user – that can be any user that has been given access – with the ability to query for the devices that belong to a specific user, by searching based on a specified UPN. Eventually, the app will show the details of the devices that belong to the specified user and the app will provide the ability to perform remote actions on those different devices. The idea of this post is to mainly describe the different configurations, to make sure that everybody understands how relatively easy it can be to create a pretty powerful app. To create the described simple remote device manager app, I’ll cover the following subjects throughout this post:

Important: For this post I choose to rely on simple built-in functionality, to show the simplicity of the mentioned products and to show the out-of-the-box powerful combination of the mentioned products. That does, however, mean that every user – with access to the remote device manager app – will be able to perform the available remote actions on the different devices. Another option for handling that is for another time. So, make sure to determine the users that should have access and scope the access to only those users.

Create an app registration in Azure AD to provide the permissions

The first action is to create an app registration in Azure AD to provide the required permissions to Microsoft Graph. That app registration contains two important configurations that are required for the different flows. The app registration needs the correct permissions and a client secret should be created for usage within the different flows. The bullets below go through the minimal configuration that is required and will make sure that the correct information is available when creating the different flows.

  • Open the Azure portal, navigate to Azure Active Directory > App registrations to create a new app registration and save the Directory (tenant) ID and the Application (client) ID for usage within the different flows
  • Navigate to API permissions, provide the app registration with at least the application API permissions of DeviceManagementManagedDevices.PrivilegedOperations.All and DeviceManagementManagedDevices.Read.All and grant admin consent for those permissions, to make sure that the different flows will have enough permissions to perform the required actions

Important: As I’m relying on the built-in functionality of Power Apps and Power Automate, I’m relying on the standard available HTTP action in the different flows. That standard action works the best and easiest (which is the idea of this post) with application API permissions. When working with delegated API permissions, for the user using the app, I would use a custom connector. More about that option in a future blog post. For now it’s standard functionality.

Note: To add additional functionalities to the app in Power Apps, or the flows in Power Automate, make sure to provide the app registration with additional API permissions, when needed.

  • Navigate to Certificates & secrets, create a new secret and save the value for usage within the different flows

Create a flow in Power Automate to get the devices of a user

The second action is to create a flow in Power Automate to get the devices of a specific user. That flow will use the app registration to query Microsoft Graph with the required permissions. The idea of the app in Power Apps is to eventually show information of the devices that belong to a specific user and to provide the ability to perform remote actions on a specifically selected device of that user. That user should be the starting point of this first flow in Power Automate. The id of the user should be used to query for the devices that belong to that user and the response of the query should eventually be put into the correct schema to filter the array with information from the response. An overview of that flow is shown in Figure 4 and the details are explained below.

  1. Open make.powerapps.com (or flow.microsoft.com) and navigate to Flows to create a new Instant cloud flow that will be triggered with PowerApps. That will automatically create the first action with the first step of the flow. That action needs no further configuration.
  2. The second step of the flow is the Azure AD – Get user action. That action will be used to get the id of the user, based on the provided user principal name, and needs the following configurations of the different values.
    • User id or Principal Name: Select Dynamic content > (PowerApps) Ask in PowerApp as value
  3. The third step of the flow is the HTTP – HTTP action. That action will be used to query Microsoft Graph for the managed devices of the provided user and needs the following configurations of the different values.
    • Method: Select GET as value
    • URI: Provide https://graph.microsoft.com/v1.0/users/{[‘id’]}/managedDevices?$select=id,deviceName,managedDeviceOwnerType,managementAgent,enrolledDateTime,lastSyncDateTime,manufacturer,model,serialNumber,operatingSystem,complianceState as value
      • the {[‘id’]} can be configured with Dynamic content > (Get user) id as value
    • Authentication: Select Active Directory OAuth as value
    • Tenant: Provide Directory (tenant) ID – as shown in Figure 1 – as value
    • Audience: Provide https://graph.microsoft.com/ as value
    • Client ID: Provide Application (client) ID – as shown in Figure 1 – as value
    • Credential Type: Select Secret as value
    • Secret: Provide the value – as shown in Figure 3 – as value

Tip: It’s also possible to store the secret in a key vault and to use the Get secret action – before the HTTP action – to retrieve the secret from the key vault. With the correct configuration of that action, that will prevent the secret from being visible in the flow configuration and in the flow run logs.

Note: To add additional properties to the selection, simply add those properties to the select-statement of the URI. In that case, also make sure to add those properties in different schemas of step 5 and step 6.

  1. The fourth step of the flow is the Data OperationsParse JSON action. That action will be used to specify the schema of the returned JSON content of the query and needs the following configurations of the different values.
    • Content: Select Dynamic content > (HTTP) Body as value
    • Schema: Provide the schema as shown below as value
{
    "type": "object",
    "properties": {
        "@@odata.context": {
            "type": "string"
        },
        "value": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string"
                    },
                    "deviceName": {
                        "type": "string"
                    },
                    "managedDeviceOwnerType": {
                        "type": "string"
                    },
                    "managementAgent": {
                        "type": "string"
                    },
                    "enrolledDateTime": {
                        "type": "string"
                    },
                    "lastSyncDateTime": {
                        "type": "string"
                    },
                    "manufacturer": {
                        "type": "string"
                    },
                    "model": {
                        "type": "string"
                    },
                    "serialNumber": {
                        "type": "string"
                    },
                    "operatingSystem": {
                        "type": "string"
                    },
                    "complianceState": {
                        "type": "string"
                    }
                }
            }
        }
    }
}
  1. The fifth and final step of this flow is Request – Response action. That action will be used to filter the array of the body (and is basically a subset of the full schema) and needs the following configurations of the different values.
    • Body: Select Dynamic content > (Parse JSON) value as value.
    • Response Body JSON Schema: Provide the schema as shown below as value
{
    "type": "array",
    "items": {
        "type": "object",
        "properties": {
            "id": {
                "type": "string"
            },
            "deviceName": {
                "type": "string"
            },
            "managedDeviceOwnerType": {
                "type": "string"
            },
            "managementAgent": {
                "type": "string"
            },
            "enrolledDateTime": {
                "type": "string"
            },
            "lastSyncDateTime": {
                "type": "string"
            },
            "manufacturer": {
                "type": "string"
            },
            "model": {
                "type": "string"
            },
            "serialNumber": {
                "type": "string"
            },
            "operatingSystem": {
                "type": "string"
            },
            "complianceState": {
                "type": "string"
            }
        }
    }
}

Note: Keep in mind that to take this flow to another level, it’s also possible to add error handling to the flow.

Create a flow in Power Automate to perform remote device actions

The third action is to create a flow in Power Automate to perform a specific remote action on a selected device. That flow will use the app registration to query Microsoft Graph with the required permissions. The idea of the app in Power Apps is to eventually show information of the devices that belong to a specific user and to provide the ability to perform remote actions on a specifically selected device of that user. That device should be the starting point of this second flow in Power Automate. The id of the device can be used to actually perform remote actions on the device. An overview of that flow is shown in Figure 5 and the details are explained below.

  1. Open make.powerapps.com (or flow.microsoft.com) and navigate to Flows to create a new Instant cloud flow that will be triggered with PowerApps. That will automatically create the first action with the first step of the flow. That action needs no further configuration.
  2. The second step of the flow is the Variable – Initialize variable action. That action will be used to set the id of the selected device in the Power App and needs the following configurations of the different values.
    • Name: Provide deviceId as value
    • Type: Select String as value
    • Value: Select Dynamic content > (PowerApps) Ask in PowerApp as value
  3. The third step of the flow is the Variable – Initialize variable action. That action will be used to set the remote action that should be performed on the selected device in the Power App and needs the following configurations of the different values.
    • Name: Provide remoteAction as value
    • Type: Select String as value
    • Value: Select Dynamic content > (PowerApps) Ask in PowerApp as value
  4. The fourth and final step of this flow is the HTTP – HTTP action. That action will be used to actually perform a remote action via Microsoft Graph on the selected device and needs the following configurations of the different values.
    • Method: Select POST as value
    • URI: Provide https://graph.microsoft.com/v1.0/deviceManagement/managedDevices/{(‘deviceId’)}/((‘remoteAction’)} as value
      • the {[‘deviceId’]} can be configured with Dynamic content > (Variables) deviceId as value
      • the {[‘remoteAction’]} can be configured with Dynamic content > (Variables) remoteAction as value
    • Authentication: Select Active Directory OAuth as value
    • Tenant: Provide Directory (tenant) ID – as shown in Figure 1 – as value
    • Audience: Provide https://graph.microsoft.com/ as value
    • Client ID: Provide Application (client) ID – as shown in Figure 1 – as value
    • Credential Type: Select Secret as value
    • Secret: Provide the value – as shown in Figure 3 – as value

Important: Keep in mind that constructing the request with a variable for the deviceId and the remoteAction, this same request can be used for every action that’s available in v1.0 of the API. Those available actions are also the limitation of the remote actions that can be added to the app by using this flow.

Tip: It’s also possible to store the secret in a key vault and to use the Get secret action – before the HTTP action – to retrieve the secret from the key vault. With the correct configuration of that action, that will prevent the secret from being visible in the flow configuration and in the flow run logs.

Note: Keep in mind that to take this flow to another level, it’s also possible to add error handling to the flow.

Create an app in Power Apps to remotely manage devices

The fourth action is to create an app in Power Apps to provide an interface to remotely manage devices. That app will use the different flows to retrieve the devices of a specific user and to perform remote actions on the devices that belong to that user. The idea of the app is to search for the devices of a specific user (as shown below in Figure 6), provide an overview of a selected device with the available remote actions (as shown below in Figure 7) and to confirm the selected remote action (as shown in Figure 8). The actual configuration of these different screens is explained below.

Open make.powerapps.com and navigate to Apps and create a new Canvas app. That will redirect to create.powerapps.com and choose a Blank app > Phone layout as the starting point.

Important: When creating and configuring the different screens, make sure to add the created flows.

Create and configure the first screen

The first screen of the app in Power Apps is used to ask the user for the input of a UPN and to show a brief overview of the devices that are related to that UPN. That can be achieved by starting with New screen > Blank (Screen1) and adding the objects as shown in Figure 6 and briefly described below with the most important parameters. The first line below describes the formatting and any special information about specific actions is described on the second line below.

  1. Label (topLabel1) – This label is used to show the name of the app on the top of the screen
    • The Text on the label is obvious, the Position is (0 , 0) and the Size is (640 x 140)
  2. Label (upnLabel1) – This label is used to show an explanation with the text input field
    • The Text on the label is obvious, the Position is (15, 150) and the Size is (610 x 70)
  3. TextInput (upnTextInput1) – This text input field is used to get the user principal name of a user as input for the app
    • The Text on the label is obvious, the Position is (15, 220) and the Size is (610 x 70)
  4. Button (searchButton1) – This button is used to get the devices that belong to the user – based on the specified user principal name – by triggering the first created flow and to store the results in a collection
    • The Text on the button is obvious, the Position is (15, 310) and the Size is (280 x 70)
    • The OnSelect action is ClearCollect(userDevices,GetUserDevices.Run(upnTextInput1.Text))
  5. Gallery (overviewGallery1) – This gallery is used to display the devices that are stored in the collection and provides the different available properties of those devices to the different objects within the gallery
    • The Position is (0, 410) and the Size is (640 x 656)
    • The Data source is userDevices
  6. Icon (overviewDeviceIcon1) – This icon is used to display an icon depending on the platform of the device
    • The Position is (16, 16), the Size is (128 x 128) and the Icon uses the following value If(ThisItem.operatingSystem="Windows",Icon.Laptop,ThisItem.operatingSystem="iOS",Icon.Tablet,ThisItem.operatingSystem="Android",Icon.Phone,Icon.ComputerDesktop) as value
  7. Label (overviewTitle1) – This label is used to display the name of the device in the gallery
    • The Text on the label is ThisItem.deviceName, the Position is (overviewDeviceIcon1.X + overviewDeviceIcon1.Width + 24, 16) and the Size is (Parent.TemplateWidth - overviewDeviceIcon1.Width - 104 x Self.Size * 1.8)
  8. Label (overviewSubtitle1) – This label is used to display the model of the device in the gallery
    • The Text on the label is ThisItem.model, the Position is (overviewTitle1.X, 64) and the Size is (overviewTitle1.Width/2 x Self.Size * 1.8)
  9. Label (overviewSubtitle3) – This label is used to display the model of the device in the gallery
    • The Text on the label is ThisItem.operatingSystem, the Position is (overviewTitle1.X+overviewTitle1.Width/2, 64) and the Size is (overviewTitle1.Width/2 x Self.Size * 1.8)
  10. Label (overviewSubtitle2) – This label is used to display the management agent of the device in the gallery
    • The Text on the label is ThisItem.managementAgent, the Position is (overviewTitle1.X, 107) and the size is (overviewTitle1.Width/2 x Self.Size * 1.8)
  11. Label (overviewSubtitle4) – This label is used to display the compliance state of the device in the gallery and the color of the text is set based on the compliance state of that device
    • The Text on the label is ThisItem.complianceState, the Position is (overviewTitle1.X+overviewTitle1.Width/2, 107), the Size is (overviewTitle1.Width/2 x Self.Size * 1.8) and the Color uses the following value If(ThisItem.complianceState="compliant",Green,ThisItem.complianceState="noncompliant",Red,Black)
  12. Icon (overviewNextArrow1) – This icon is used to navigate to the next screen for the device in the gallery
    • The icon is Next, the Position is (Parent.TemplateWidth - Self.Width - 5, (Parent.TemplateHeight/2) - (Self.Height/2)) and the Size is (64 x 64)
    • The OnSelect action is Navigate(Screen2,ScreenTransition.UnCoverRight)
  13. Rectangle (overviewSeparator1) – This rectangle is used as a separator between the different devices in the gallery
    • The Position is (0, Parent.TemplateHeight - 1) and the Size is (Parent.TemplateWidth x 1)
  14. Label (bottomLabel1) – This label is used to show the name of the author on the bottom of the screen
    • The Text on the label is obvious, the Position is (0, 1066) and the Size is (640 x 70)

Important: The names of the objects are also described, as some of the names are also used for configuring other objects. The different objects can be used within all screens in the app.

Create and configure the second screen

The second screen of the app in Power Apps is used to provide a more detailed overview of a selected device and to provide buttons to perform remote actions on that device. That can be achieved by starting with New screen > Blank (Screen2) and adding the objects as shown in Figure 7 and briefly described below with the most important parameters. The first line below describes the formatting of the objects and any special information about specific actions is described on the second line below.

  1. Label (topLabel2) – This label is used to show the name of the app on the top of the screen
    • The Text on the label is obvious, the Position is (0 , 0) and the Size is (640 x 140)
  2. Label (upnLabel2) – This label is used to show the earlier specified user principal name on the top of the screen
    • The Text on the label is upnTextInput1.Text, the Position is (0 , 140) and the Size is (640 x 140)
  3. Label (deviceIdLabel1) – This label is used to show an explanation with the label showing the device id
    • The Text on the label is obvious, the Position is (15 , 233) and the Size is (280 x 60)
  4. Label (deviceIdLabel2) – This label is used to show the device id of the – in the gallery – selected device
    • The Text on the label is overviewGallery1.Selected.id, the Position is (295 , 233) and the Size is (330 x 60)
  5. Label (deviceNameLabel1) – This label is used to show an explanation with the label showing the device name
    • The Text on the label is obvious, the Position is (15 , 293) and the Size is (280 x 60)
  6. Label (deviceNameLabel2) – This label is used to show the device name of the – in the gallery – selected device
    • The Text on the label is overviewGallery1.Selected.deviceName, the Position is (295 , 293) and the Size is (330 x 60)
  7. Label (deviceOwnerLabel1) – This label is used to show an explanation with the label showing the device owner
    • The Text on the label is obvious, the Position is (15 , 353) and the Size is (280 x 60)
  8. Label (deviceOwnerLabel2) – This label is used to show the device owner of the – in the gallery – selected device
    • The Text on the label is overviewGallery1.Selected.managedDeviceOwnerType, the Position is (295 , 353) and the Size is (330 x 60)
  9. Label (managementAgentLabel1) – This label is used to show an explanation with the label showing the agent
    • The Text on the label is obvious, the Position is (15 , 413) and the Size is (280 x 60)
  10. Label (managementAgentLabel2) – This label is used to show the agent of the – in the gallery – selected device
    • The Text on the label is overviewGallery1.Selected.managementAgent, the Position is (295 , 413) and the Size is (330 x 60)
  11. Label (enrollmentDateLabel1) – This label is used to show an explanation with the label showing the enrollment date
    • The Text on the label is obvious, the Position is (15 , 473) and the Size is (280 x 60)
  12. Label (enrollmentDateLabel2) – This label is used to show the enrollment date of the – in the gallery -selected device
    • The Text on the label is overviewGallery1.Selected.enrolledDateTime, the Position is (295 , 473) and the Size is (330 x 60)
  13. Label (activityDateLabel1) – This label is used to show an explanation with the label showing the activity date
    • The Text on the label is obvious, the Position is (15 , 533) and the Size is (280 x 60)
  14. Label (activityDateLabel2) – This label is used to show the (latest) activity date of the – in the gallery -selected device
    • The Text on the label is overviewGallery1.Selected.lastSyncDateTime, the Position is (295 , 533) and the Size is (330 x 60)
  15. Label (manufacturerLabel1) – This label is used to show an explanation with the label showing the manufacturer
    • The Text on the label is obvious, the Position is (15 , 593) and the Size is (280 x 60)
  16. Label (manufacturerLabel2) – This label is used to show the manufacturer of the – in the gallery – selected device
    • The Text on the label is overviewGallery1.Selected.manufacturer, the Position is (295 , 593) and the Size is (330 x 60)
  17. Label (modelLabel1) – This label is used to show an explanation with the label showing the model
    • The Text on the label is obvious, the Position is (15 , 653) and the Size is (280 x 60)
  18. Label (modelLabel2) – This label is used to show the model of the – in the gallery – selected device
    • The Text on the label is overviewGallery1.Selected.model, the Position is (295 , 653) and the Size is (330 x 60)
  19. Label (serialNumberLabel1) – This label is used to show an explanation with the label showing the serial number
    • The Text on the label is obvious, the Position is (15 , 713) and the Size is (280 x 60)
  20. Label (serialNumberLabel2) – This label is used to show the serial number of the – in the gallery – selected device
    • The Text on the label is overviewGallery1.Selected.serialNumber, the Position is (295 , 713) and the Size is (330 x 60)
  21. Label (operatingSystemLabel1) – This label is used to show an explanation with the label showing the platform
    • The Text on the label is obvious, the Position is (15 , 773) and the Size is (280 x 60)
  22. Label (operatingSystemLabel2) – This label is used to show the platform of the – in the gallery – selected device
    • The Text on the label is overviewGallery1.Selected.operatingSystem, the Position is (295 , 773) and the Size is (330 x 60)
  23. Label (complianceStateLabel1) – This label is used to show an explanation with the label showing the compliance
    • The Text on the label is obvious, the Position is (15 , 833) and the Size is (280 x 60)
  24. Label (complianceStateLabel2) – This label is used to show the compliance state of the – in the gallery – selected device and the color of the text is set based on the compliance state of that device
    • The Text on the label is overviewGallery1.Selected.complianceState, the Position is (295 , 833), the Size is (330 x 60) and the Color uses the following value If(ThisItem.complianceState="compliant",Green,ThisItem.complianceState="noncompliant",Red,Black)
  25. Button (syncButton1) – This button is used to set the required variables – for the remote sync action – for usage within the verification and to navigate to the verification screen
    • The Text on the button is obvious, the Display mode is DisplayMode.Edit, the Position is (0, 916) and the Size is (152.5 x 70)
    • The OnSelect action is Set(deviceId,overviewGallery1.Selected.id); Set(remoteAction,"syncDevice"); Set(verificationValue,"sync"); Navigate(Screen3,ScreenTransition.UnCoverRight)
  26. Button (remoteLockButton1) – This button is only enabled for specific platforms and is used to set the required variables – for the remote lock action – for usage within the verification and to navigate to the verification screen
    • The Text on the button is obvious, the Display mode is If(overviewGallery1.Selected.operatingSystem="Windows",DisplayMode.Disabled,DisplayMode.Edit), the Position is (163, 916) and the Size is (152.5 x 70)
    • The OnSelect action is Set(deviceId,overviewGallery1.Selected.id); Set(remoteAction,"remoteLock"); Set(verificationValue,"remote lock"); Navigate(Screen3,ScreenTransition.UnCoverRight)
  27. Button (resetPasscodeButton1) – This button is only enabled for specific platforms and is used to set the required variables – for the reset passcode action – for usage within the verification and to navigate to the verification screen
    • The Text on the button is obvious, the Display mode is If(overviewGallery1.Selected.operatingSystem="iOS",DisplayMode.Edit,DisplayMode.Disabled), the Position is (325, 916) and the Size is (152.5 x 70)
    • The OnSelect action is Set(deviceId,overviewGallery1.Selected.id); Set(remoteAction,"resetPasscode"); Set(verificationValue,"reset passcode"); Navigate(Screen3,ScreenTransition.UnCoverRight)
  28. Button (restartButton1) – This button is only enabled for specific platforms and is used to set the required variables – for the remote restart action – for usage within the verification and to navigate to the verification screen
    • The Text on the button is obvious, the Display mode is If(overviewGallery1.Selected.operatingSystem="Windows",DisplayMode.Edit,DisplayMode.Disabled), the Position is (487, 916) and the Size is (152.5 x 70)
    • The OnSelect action is Set(deviceId,overviewGallery1.Selected.id); Set(remoteAction,"rebootNow"); Set(verificationValue,"restart"); Navigate(Screen3,ScreenTransition.UnCoverRight)
  29. Button (retireButton1) – This button is only enabled for specific platforms and is used to set the required variables – for the remote retire action – for usage within the verification and to navigate to the verification screen
    • The Text on the button is obvious, the Display mode is DisplayMode.Edit, the Position is (0, 996) and the Size is (152.5 x 70)
    • The OnSelect action is Set(deviceId,overviewGallery1.Selected.id); Set(remoteAction,"retire"); Set(verificationValue,"retire"); Navigate(Screen3,ScreenTransition.UnCoverRight)
  30. Button (wipeButton1) – This button is only enabled for specific platforms and is used to set the required variables – for the remote restart action – for usage within the verification and to navigate to the verification screen
    • The Text on the button is obvious, the Display mode is If(overviewGallery1.Selected.operatingSystem="macOS",DisplayMode.Disabled,DisplayMode.Edit), the Position is (163, 996) and the Size is (152.5 x 70)
    • The OnSelect action is Set(deviceId,overviewGallery1.Selected.id); Set(remoteAction,"wipe"); Set(verificationValue,"wipe"); Navigate(Screen3,ScreenTransition.UnCoverRight)
  31. Button (updateDefenderButton1) – This button is only enabled for specific platforms and is used to set the required variables – for the remote Defender action – for usage within the verification and to navigate to the verification screen
    • The Text on the button is obvious, the Display mode is If(overviewGallery1.Selected.operatingSystem="Windows",DisplayMode.Edit,DisplayMode.Disabled), the Position is (325, 996) and the Size is (152.5 x 70)
    • The OnSelect action is Set(deviceId,overviewGallery1.Selected.id); Set(remoteAction,"windowsDefenderUpdateSignatures"); Set(verificationValue,"update Windows Defender signatures"); Navigate(Screen3,ScreenTransition.UnCoverRight)
  32. Button (freshStartButton1) – This button is only enabled for specific platforms and is used to set the required variables – for the remote restart action – for usage within the verification and to navigate to the verification screen
    • The Text on the button is obvious, the Display mode is If(overviewGallery1.Selected.operatingSystem="Windows",DisplayMode.Edit,DisplayMode.Disabled), the Position is (487, 996) and the Size is (152.5 x 70)
    • The OnSelect action is Set(deviceId,overviewGallery1.Selected.id); Set(remoteAction,"cleanWindowsDevice"); Set(verificationValue,"fresh start"); Navigate(Screen3,ScreenTransition.UnCoverRight)
  33. Icon (backIcon1) – This icon is used to navigate to the previous screen with the devices overview in the gallery
    • The icon is Back, the Position is (15, 1076) and the Size is (50 x 50)
    • The OnSelect action is Back(ScreenTransition.UnCover)
  34. Label (bottomLabel1) – This label is used to show the name of the author on the bottom of the screen
    • The Text on the label is obvious, the Position is (0, 1066) and the Size is (640 x 70)

Important: The names of the objects are also described, as some of the names are also used for configuring other objects. The different objects can be used within all screens in the app.

Create and configure the third screen

The third screen of the app in Power Apps is used to provide a confirmation of the selected remote action. That can be achieved by starting with New screen > Blank (Screen3) and adding the objects as shown in Figure 8 and briefly described below with the most important parameters. The first line below describes the formatting and any special information about specific actions is described on the second line below.

  1. Label (topLabel3) – This label is used to show the name of the app on the top of the screen
    • The Text on the label is obvious, the Position is (0 , 0) and the Size is (640 x 140)
  2. HTLM Text (questionHtmlText1) – This HTML text is used to show the confirmation summary of the remote action by showing a message that contains the provided user principal name, the selected device and the remote action
    • The Text on the HTML text is "<center>Are your sure that you want to trigger a <b>" & verificationValue & "</b> action on <b>" & overviewGallery1.Selected.deviceName & "</b> of <b>" & upnTextInput1 &"</b>?</center>", the Position is (15 , 314) and the Size is (610 x 210)
  3. Button (yesButton1) – This button is used to actually perform the remote action, for the selected device, by triggering the second created flow with the different created variables as input, and to return to the previous screen
    • The Text on the button is obvious, the Position is (15, 720) and the Size is (300 x 70)
    • The OnSelect action is PerformRemoteAction.Run(deviceId,remoteAction); Back(ScreenTransition.UnCover)
  4. Button (noButton1) – This button is used to cancel the remote action, for the selected device, and to return to the previous screen
    • The Text on the button is obvious, the Position is (325, 720) and the Size is (300 x 70)
    • The OnSelect action is Back(ScreenTransition.UnCover)
  5. Label (bottomLabel1) – This label is used to show the name of the author on the bottom of the screen
    • The Text on the label is obvious, the Position is (0, 1066) and the Size is (640 x 70)

Important: The names of the objects are also described, as some of the names are also used for configuring other objects. The different objects can be used within all screens in the app.

User experience with the remote device manager app

Let’s end this post with the user experience with the end result of the created remote device manager app. Below in Figure 9 is an overview of the initial state of the first screen. That provides a clean screen that simply asks the user to specify the UPN of a specific user and to press search to find the devices that belong to that user. Below in Figure 10 is an overview of the device results in the first screen. That provides a quick overview of the different devices that belong to that user and includes information about the name, model, platform, management and compliance of the devices.

Below in Figure 11 is an overview of the device details in the second screen. That provides an overview of the details of the selected device and enables the applicable buttons for the different available remote actions. Below in Figure 12 is an overview of the confirmation message in the third screen. That provides a message that includes the action, the device and the UPN of the user and asks the user to confirm. Once confirmed, the action will be triggered.

More information

For more information about the different subjects that are used throughout this post, refer to the following docs.

36 thoughts on “Introducing a simple remote device manager app for Microsoft Intune”

    • Hi Robert,
      Yes! I’ve briefly mentioned it as a tip. You can use a Get secret step with the Secure outputs configuration to prevent the Secret from being shown in the flow configuration and the flow usage logs.
      Regards, Peter

      Reply
  1. Hey Peter is they anyway your could export your power app to look at. I feel like i am missing setting when tryin to create the pages.

    Reply
  2. Great post and blog.
    I’m having an issue after the import. When I’m trying to Restart or Fresh a machine start I’m getting the following error:

    TriggerRemoteActionV2.Run failed: { “code”: “InvokerConnectionOverrideFailed”, “message”: “Failed to parse invoker connections from trigger ‘manual’ outputs. Exception: Could not find any valid connection for connection reference name ‘shared_intune-20device-20actions-5f090026673b397ced-5f9a29927a6abfaac4_1’ in APIM tokens header.” }

    I made the necessary connections in Power Automate for the Intune actions and also the permissons within the Azure AD app registation.

    Reply
  3. Thanks for the great post!
    A question:
    Everything looks fine in the flow and powerapp. The only strange thing is that my powerapp is not returning any records in the gallery. My flow is reporting the requested data as expected in the response step. I can also select the expected fields in the gallery when selecting the userdevices collection in the. Powerapp. But they are empty.

    Any idea?

    Reply
  4. I have the same prolem like Harm….flow seems to work fine, reports items but in the app itself the collection stays empty…

    Reply
  5. Hi Peter,
    First things first: thanks for sharing so much knowledge with us. Good for me and my job to find this blog some time ago.
    Excellent post with clear explanations, easy steps to follow… Flow and App worked perfectly in my lab. And I’ve been playing with getting other device fields data, so I’ve been able to list imei, managedDeviceName, deviceCategoryDisplayName… However, for the “notes” field I always get a “null” value. This is how I specify “notes” field when I provide the Schema in the Parse JSON step:
    “notes”: {“type”:[“string”,”null”]}
    I couldn’t find out how to solve this. The truth is that even in the Graph explorer we don’t get any data from the notes field.
    I don’t know, maybe this is an out-of-the-box limitation. However I’ll appreciate any clue if you think this can be solved.
    Thanks and have a nice day

    Reply
  6. Peter,

    so we have been working with this app for a while now and all works fine. However, when we share the app with a user who hasn’t got the “Intune administrator”-role in Azure AD, they can’t lookup user devices….

    I thought that’s why we do the step to set delegated api permissions but i can’t figure out how to make this work for those users….am i missing something?

    Thx in advance

    Reply
      • Yes, I figured that out indeed. But the problem is, for some reason when I change to application API permissions, the app doesn’t work at all anymore….When running the app or even testing the custom connector, everyone gets message that there is no authorization…

        Anyone has experience with this?

        (my goal is that a ‘default’ user with no roles can still acces the app)

        Reply
  7. Hi Robin,

    thank you very much for this post. I am new to Power Platform, and I started to learn by doing. I am not sure if you will respond because it’s almost 2 years old. I followed all the steps showed above and everything work.

    Now when I run the flow in PowerApps and I save the content into a collection, the collection is empty! Nothing to see inside. I deleted the flow and recreated it and also created a new app and re-run the flow, but the collection is still empty!
    I run out of idea. Do you have any idea what could be the reason?

    Regards,
    Yohan

    Reply
      • Hi Peter,
        Thank you for you reply.
        So yes the flow works fine in the Flow editing menu and also when I use the Graph Explorer.

        But when I run it in power apps, nothing’s happen. As I said the collection remain empty.
        Regards,
        Yohan

        Reply
      • Hi Peter,

        yes, I did it. The flow works fine with the graph explorer and also in the edit menu. I tested it first before running it in PowerApps. But still when I create my collection like this: ClearCollect(DeviceCollection, Flowname.Run(“mail”)), there is no data inside.

        Reply
      • Hi Peter,
        I found a solution to my problem. I designed my flow differently than yours and I was able to select exactly from the HTML the attributes I needed. I have more control of the data and the structure.
        Thanks again for your engagement.

        Regards

        Reply
  8. Hi Peter, nice post! I would rather get device data from Azure instead of Intune. How would I figure out the URI to get that info (e.g. https://graph.microsoft.com/v1.0/users/{[‘id’]}/managedDevices?$select=id,deviceName,managedDeviceOwnerType,managementAgent,enrolledDateTime,lastSyncDateTime,manufacturer,model,serialNumber,operatingSystem,complianceState)

    Thanks!

    Reply
  9. Unable to select a Azure AD connection or device actions conection, despite setting acustom connector up (using the API walkthrough as described)

    Reply

Leave a Reply to Robert 28 Cancel reply

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