Tag Archives: Microsoft Flow

Blog Series – Power’ing up your Home Office Lights: Part 9 – Using Microsoft Graph to get Teams Presence and show state in PowerApp.

This blog post is part of the Blog Series: Power’ing up your Home Office Lights with Power Platform. See introduction post for links to the other articles in the series:
https://gotoguy.blog/2020/12/02/blog-series—powering-up-your-home-office-lights-using-power-platform—introduction/

In this part 9 we will use Microsoft Graph to get the logged in user Teams Presence, and show that state in the PowerApp.

I have previously written another post on Teams Presence, Microsoft Graph and requirements here: Subscribing to Teams Presence with Graph API using Power Platform | GoToGuy Blog. If you want to dig deeper into that I would recommend that you read that post, but for now in this article I will show how you can get your Teams Presence into the Hue Power App.

Teams Presence is currently available in the beta endpoint of Microsoft Graph here: https://graph.microsoft.com/beta/me/presence

If you quickly want to check your own Teams Presence via the Microsoft Graph you can try the following. Just click this link that will launch in Graph Explorer: https://developer.microsoft.com/en-us/graph/graph-explorer?request=me%2Fpresence&method=GET&version=beta&GraphUrl=https://graph.microsoft.com

Just remember to consent to the Presence.Read permission as shown below:

As always when calling Microsoft Graph, we need to authenticate to Azure AD and authorize to Graph API to get an access token for quierying resources. And if we want to do that from Power Platform we need to create an app registration for that in Azure AD.

App Registration in Azure AD

This step might be dependent on if your tenant administrator has restricted the users’ right to create app registrations. If so, you will need to log into your tenant as a Global Administrator or Application Administrator, or get help from your IT admin to create the following App Registration in Azure AD.

If not, the following operations don’t require admin consent or permissions, so you can go ahead and create the App Registration. At the Azure AD Portal, go to https://aad.portal.azure.com, App Registrations and add a new like below:

Just leave the Redirect URI blank for now and click register.

Next, click on API Permissions, and click add a permission and select Microsoft Graph at the top, click on Delegated permissions, and add the Presence.Read permission as shown below:

You should now have the following permissions:

Next, go to Certificates & secrets, add a new client secret with a description, and select your chosen expiry:

Click Add and copy the secret value which will showed only this once. Save this secret for now, we will need it later. Also, go back to overview and copy the Application (Client) Id for later. We will need that as well.

There is just one thing left in this app registration, but for now we need to switch over to Power Platform for creating the Custom Connector.

Custom Connector in Power Platform for Microsoft Graph

We will now create a custom connector in Power Platform to reference this App Registration and get the Presence. Log either into make.powerapps.com, or flow.microsoft.com, for this next step.

Under the Data menu, select Custom Connectors. Select to add new connector from blank, and give it a name:

Select Continue, and on the General page, type graph.microsoft.com as host. You can also upload an icon and a description:

On the Security page, select OAuth 2.0 as type, and Azure Active Directory for Identity Provider. Client Id and Secret is the App Id and Secret from the App Registration earlier. Resource Url is https://graph.microsoft.com, and specify the scope to be Presence.Read:

After that, click on “Create Connector”, and the the “Redirect URL” will be populated:

Copy this URL and add it as a Web platform Redirect URI back in the Azure AD App Registration:

Back in the Custom Connector, go to Step 3. Definition, and click New Action. Type in a Summary “Get Presence” and Operation ID “GetPresence”, and under Request click Import from sample. Specify Get as verb, and URL to https://graph.microsoft.com/beta/me/presence, like below, and click Import:

Go to the Response section, and click on the Default response. Click on Import from sample and specify Content-Type application/json for Header response, and for Body, paste in the response you got when you tried the presence query in Graph Explorer in the beginning of this blog post:

The action should now look like this:

We can now proceed to Test. Click on Update Connector and under 4. Test click on “New connection”, and then Create:

Sign in and then accept the application to read your presence information and profile as shown below:

I can now test the GetPresence action with the signed in connection, and verify a successful response. In my case my availability just now is “Away”:

With the Custom Connector now ready, I can proceed to add this status to my PowerApp.

Customizing the Hue Power App to get Presence

Back in my Power App i created in earlier parts of this blog series, I want this icon to reflect my Teams Presence status. I will start simple by adding an OnSelect event to this icon, that will get my Presence status using the Custom Connector.

Under View menu, and Data, select to add the custom connector as a new connection to the PowerApp:

On the OnSelect event for the presence icon, I will use Set function and a variable called MyPresence, where I run the Custom connector and GetPresence operation like below:

Set(MyPresence,MSGraphPresenceConnector.GetPresence())

This is how it looks:

Holding down ALT button, I can now click on the Icon to run the OnSelect event, and after that I can go to the View menu again, then under variables I will find the MyPresence variable. When looking into that record, I can verify that I indeed have received my presence status:

The next part would be to update the color of the Icon to reflect the status. I also, for now at least want an extra label that specifies the status as a text value. Lets start by that. I add a label next to the Icon and then set the Text property to “MyPresence.availability”, as shown under:

You should now be able to change the Teams Presence and then click on the Icon in the Hue Power App to update presence status text:

From the Graph Documentation, presence resource type – Microsoft Graph beta | Microsoft Docs, the following values are possible for presence availability, and I have added the suggested colors for these statuses:

  • Away (Yellow)
  • Available (Green)
  • AvailableIdle (Green)
  • Busy (Red)
  • BusyIdle (Red)
  • BeRightBack (Yellow)
  • DoNotDisturb (Red)
  • Offline (Light Grey)
  • PresenceUnknown (White)

So what remaining is that I want to update the color of the Teams Presence Icon also to reflect the status. And for this I chose to use the Switch function, where I evaluate the MyPresence.availability variable, and have different results:

Switch( MyPresence.availability, "Away", "Result1", "Available", "Result2", "AvailableIdle", "Result3", "Busy", "Result4", "BusyIdle", "Result5", "BeRightBack", "Result6", "DoNotDisturb", "Result7", "Offline", "Result8", "PresenceUnknown", "Result9", "DefaultResult" )

I will use that Switch formula to set the Fill property of the Icon, which now is manually set to Red like this:

So after picking the colors, I end up with this formula:

Switch( MyPresence.availability, "Away", RGBA(253, 185, 19, 1), "Available", RGBA(146, 195, 83, 1), "AvailableIdle", RGBA(146, 195, 83, 1), "Busy", RGBA(196, 49, 75, 1), "BusyIdle", RGBA(196, 49, 75, 1), "BeRightBack", RGBA(253, 185, 19, 1), "DoNotDisturb", RGBA(196, 49, 75, 1), "Offline", RGBA(128, 130, 133, 1), "PresenceUnknown", RGBA(255, 255, 255, 1), RGBA(0, 0, 0, 0) )

Adding this to the Fill property of the Icon:

After this you should be able to change your Teams Presence status, and then click on the Icon to update the status in the PowerApp:

One last ting remains before I conclude this blog post, and that is that I want to update the presence status everytime I navigate to this screen in my PowerApp. I’ll just add the following line to the OnSelect event for the Control Lights button on the main screen:

Summary & Next Steps

In this blog post I have shown how you can get the Teams Presence status into the Hue Power App, and for now the status is manually updated either by clicking on the status Icon, or when navigating to the lights screen.

In the next, and last part, of this blog series, I will show how you can subscribe to Microsoft Graph changes, so that you can automatically get status updates.

Thanks for reading so far, see you in the last part 10 of this blog series!

Blog Series – Power’ing up your Home Office Lights: Part 8 – Using Power Automate Flows to Get and Set Lights State

This blog post is part of the Blog Series: Power’ing up your Home Office Lights with Power Platform. See introduction post for links to the other articles in the series:
https://gotoguy.blog/2020/12/02/blog-series—powering-up-your-home-office-lights-using-power-platform—introduction/

In Part 7 we built the main screen of the PowerApp, the topic for today is to build Flows and the PowerApp screen for controlling the Hue Lights:

If you want a quick summary of how this screen works, take a look at this video:

<YOUTUBE VIDEO PROCESSING, AVAILABLE SOON>

Building the Lights Control Screen

Start by adding another screen to the Hue PowerApp. If you have used a custom background color, logo and other graphical elements like I have you can do the same for this screen also. In addition to the label controls I’ve added for texts, I’ve added the following controls to my Hue PowerApp:

  • Small circle icons/shapes to reflect color states.
  • Toggle controls to set Light state On/Off and sync with Teams Presence On/Off.
  • Dropdown list for listing the Hue Lights.
  • Slider control for setting Brightness.
  • I’ve also added a Timer control and set it to not visible.

After adding and customizing the controls and named your controls after your chosen naming convention, your Hue PowerApp might look like the following:

Now we need to create a couple of Flows (as of today these are names Cloud Flows) for getting and setting Light State.

Creating Flow for Getting Lights and State

Create a new Instant Flow with PowerApps as Trigger. Name the Flow “Hue – Get Lights and State”. First add a Compose action, name the action “Access Token and User Name”, and select Ask in PowerApps under Dynamic Content:

Next, add a Parse JSON action below:

You can use the following schema:

{
    "type": "object",
    "properties": {
        "access_token": {
            "type": "string"
        },
        "username": {
            "type": "string"
        }
    }
}

We are now ready to query for the Lights for my Hue Remote API. But first it is helpful to understand a little about how the Hue Remote API returns lights. Earlier this year I published this blog post about exploring the Hue Remote API using Postman: Remote Authentication and Controlling Philips Hue API using Postman | GoToGuy Blog. For example when I query for all lights, https://api.meethue.com/bridge/{{username}}/lights/, I get a response similar to this:

The special thing to note here is that Hue returns every light as a named object identified by a light number. This is not an Array, so you cannot loop through that as you would expect. So I needed to think a little different in my solution.

I decided to create my own Array, and get the Lights one-by-one. For this I needed to start at light number “1”, and then do until some maximum value. I have currently 13 lights, so I created a variable for “13”. It makes it a little static, but at least it works with as little hassle as possible.

First add an Initialize variable action, of type Array and name arrayLights, and using the expression json('[]') as an empty json array as value:

Next, add two more Initialize variables actions, both of type Integer and named LightNumber with value 1, and NumberOfLights with value 13 (or whatever number of lights you have!).

Now, add a “Do until” action, setting LightNumber is greater than NumberOfLights as loop control:

Inside the Do until-loop, add a HTTP action, where we will run a GET query against the https://api.meethue.com/bridge/<whitelist identifer>/lights/<lightnumber>, using the access_token as a Bearer token in the Authorization Header:

This will return the first light state. Add a Append to array variable action, selecting the “arrayLights”, and adding the value like following:

This will add the Light number, the name of the Light source (body('Get_Light')?['name']) and if state on is true or false (body('Get_Light')?['state/on']).

Next action is to add an Increment variable action to increase the LightNumber by 1:

And last, outside the Do until, add a Response action so that we can return the data to the PowerApp. The important part here is to specify status code 200 and content-type application/json, and return the arrayLights variable as shown below:

Getting the Lights and State to the PowerApp

Now that we have to Flow for getting Lights and State, we can get that data into the PowerApp. Back in the PowerApp, select the Button control in the Main Screen with the name Control Lights. Click on the Action menu, and Power Automate to link the “Hue – Get Lights” and State Flow, and add the following lines to the OnSelect event:

Navigate(screenPresenceLights);
Set(wait,true);
ClearCollect(MyHueLights,'Hue-GetLightsandState'.Run(JSON(HueResponse)));
Set(wait,!true)

To explain, the Navigate(<screen>), is for changing to the other screen of course. I also use the Set(wait,true) and Set(wait,!true) on either side of the Flow run to make the PowerApp appear busy. And then, I save all the Lights and State back from the response from the Flow to a Collection, using ClearCollect and the Collection name “MyHueLights”. The Flow run expects that I supply the access_token and username, which I already has as a record variable in the shape of “HueResponse”. So, I’ll just add a JSON(..) function around that.

We can test. Hold down the “ALT” on your keyboard, and click on the “Control Lights” button. After this, go to the View menu and select Collections. You should see the “MyHueLights” collection, and a preview of the first 5 items:

Now we can get that data in to the PowerApp controls. Select the Drop Down list control, and set the Items property to “MyHueLights” and the Value to “Name”:

This should fill the Drop Down with Light names. Next, for the Drop Down list OnChange event, add the following:

Set(SelectedLight,(ddlMyLights.SelectedText));
Set(CheckStatus,false);
If(SelectedLight.State="True",Set(CheckStatus,true);Set(LightState,true),
Set(CheckStatus,true);Set(LightState,false)
)

So in the above expression for the OnChange event, I set a variable “SelectedLight” to the selected text from the Drop Down, and then I’m manipulating another variable with set “CheckStatus” and set “LightState”, depending on if the state on is true or false.

Proceeed to select the toggleLightState control, and set the Default property to the variable “LightState” and Reset property to “CheckStatus”:

We now have what we need for getting the Lights and State into the PowerApp. The next thing we need to build is to actually set Light states and colors back to the Hue Remote API.

Creating Flow for Setting Lights and State

Create a new Instant Flow with PowerApps as trigger, and name it “Hue – Set Light and State”. Start by adding the same two Compose actions as the “Hue – Get Light and State” Flow:

Next, add an Initialize variable action, with the name “Initialize LightNumber”, and select “Ask in PowerApps” under Dynamic content so that this input will be submitted from the PowerApp:

After that, add a Compose action. Name it “Body State”, and select “Ask in PowerApps” for input:

This input parameter is where we will supply the light state, colors etc.

Next add a Parse JSON action, using the outputs of the previous Body State input:

You can use the following schema:

{
    "type": "object",
    "properties": {
        "on": {
            "type": "boolean"
        },
        "xy": {
            "type": "array",
            "items": {
                "type": "number"
            }
        },
        "bri": {
            "type": "integer"
        }
    }
}

After this, add an HTTP action, using method PUT, and the address https://api.meethue.com/bridge/<whitelist identifier>/lights/<lightnumber>/state, and including the access_token as a Bearer token in the Authorization Header. For Body, construct the following JSON body:

And last, add a Response action to return status code and body to the PowerApp:

We now have a Flow in which we can call to set the light states in the PowerApp.

Control Light States from PowerApp

Lets start by turning selected Lights on and off. Select the Toggle control for Light State, and for the “OnCheck” event add the Power Automate Flow “Hue – Set Light and State” under the Action menu. For the OnCheck event add the following expression:

Set(MyLightState, "{'on':true }");
'Hue-SetLightandState'.Run(JSON(HueResponse), SelectedLight.LightNumber , MyLightState)

And for the UnCheck event:

Set(MyLightState, "{'on':false }");
'Hue-SetLightandState'.Run(JSON(HueResponse), SelectedLight.LightNumber , MyLightState)

So as you can see above, I’m using a variable named “MyLightState”, for dynamically storing the different light states I want to set and submit to the Flow. The ‘Hue-SetLightandState.Run’ takes three inputs in the form of access_token and username (via HueResponse variable), then selected LightNumber, and the MyLightState variable.

Next, lets go to the Slider control for setting Brightness. On the OnChange event, add the following expression:

Set(MyLightState, "{'bri': " & sliderBrightness.Value & " }");
'Hue-SetLightandState'.Run(JSON(HueResponse), SelectedLight.LightNumber , MyLightState)

Here I’m changing the state via the ‘bri’ value, and the sliderBrightness.Value. Btw, the Slider is set to minimum 2 and max 254, to support the values expected by the Hue API for ‘bri’.

And then finally we can set the color states for the three icons I have prepared. I have created pre-defined colors reflecting my presence status, green for available, red for busy and yellow for away.

For each of these, change the “OnSelect” event to the following:

Green (Available):

Set(MyLightState, "{'on':true, 'xy': [ 0.358189, 0.556853 ], 'bri':" & sliderBrightness.Value & " }");
 'Hue-SetLightandState'.Run(JSON(HueResponse), SelectedLight.LightNumber , MyLightState)

Red (Busy):

Set(MyLightState, "{'on':true, 'xy': [ 0.626564, 0.256591 ], 'bri':" & sliderBrightness.Value & " }");
 'Hue-SetLightandState'.Run(JSON(HueResponse), SelectedLight.LightNumber , MyLightState)

Yellow (Away):

Set(MyLightState, "{'on':true, 'xy': [ 0.517102, 0.474840 ], 'bri':" & sliderBrightness.Value & " }");
 'Hue-SetLightandState'.Run(JSON(HueResponse), SelectedLight.LightNumber , MyLightState)

A few words about the colors, this is something that could be a little difficult to get a grasp on. Hue has an explanation on the CIE color space and the “xy” resource here: Core Concepts – Philips Hue Developer Program (meethue.com).

You can also see some conversion functions here: Color Conversion Formulas RGB to XY and back – Philips Hue Developer Program (meethue.com)

Basically I’ve tested and learned. A good tip is to set the color you like using the official Hue Mobile App, and then read the state for the light.

Summary and Next Steps

The Hue PowerApp has now a working solution for getting Lights and State, as well as manually controlling colors, toggle on and off, and setting brightness.

In the next part of this blog post series, we will look into getting the presence status from Teams and show that in the Power App.

Thanks for reading!

Blog Series – Power’ing up your Home Office Lights: Part 7 – Building the PowerApp for Hue to Get Config and Link user

This blog post is part of the Blog Series: Power’ing up your Home Office Lights with Power Platform. See introduction post for links to the other articles in the series:
https://gotoguy.blog/2020/12/02/blog-series—powering-up-your-home-office-lights-using-power-platform—introduction/

With the Power Automate Flows we’ve built in the previous parts, we should now be able to get the Link and Whitelist the user and get the Hue Bridge Configuration details. It is time to build the main screen of the “Hue PowerApp”!

Here is a short video where I talk about the basics of the main screen of the PowerApp we are going to build:

Building the PowerApp and Main Screen

In my solution I wanted to build a canvas app with a phone layout, to be able to use it when on my mobile as well. Start by logging in to make.powerapps.com, and creating a new app from Blank, and either phone or tablet layout by your preference:

This next step is up to your preference and personal choice, but what I did was the following:

  • Added a custom background color from your palette (if you have a branding profile) or you could choose one of the built-in themes:
  • Add a Header logo
  • Add elements like frames and icons. I often use a Label control and set the border for it to create a frame like figure.
  • Add label controls for your text and placeholders for where you will update values later. Set font colors for labels and labels where you will have values.
  • Add some Images for where you want to add an action to the OnSelect event.
  • Add Button controls or Icons for navigating between screens.
  • Use a naming convenvtion for your controls.

In the end, adding and formatting all controls, and before I add any data to the PowerApp, my Hue PowerApp ends up like this:

I’ve uploaded Images for the Authorization and Linking, for your convenience I’ve attached those here:

After finishing the PowerApp main screen design, we can proceed to adding actions and getting data.

Connecting the PowerApp to Power Automate Flows

Start by selecting the Refresh Icon, on the Action menu, click the On Select button to change to the OnSelect event, and click the Power Automate button:

Under Data, select to associate the “Hue – Get Access Token and Config” Flow:

This will start populating the OnSelect event field, which you would edit so that you use the “Se”t function and save the response from calling the Flow in the variable HueResponse like this: Set(HueResponse,'Hue-GetAccessTokenandConfig'.Run())

Lets test this action. Before this I have removed my user from the Microsoft List “Elven Hue Users”, this list is empty now:

Hold down the “ALT” button on your keyboard, and click on the Refresh icon. The Flow will now run, you will see the small dots flying over the screen, but you won’t see any data yet. But you can check the contents of the “HueResponse” variable. Do this by going to the View menu, and click on the “Variables” button. From there you should see the HueResponse variable, it is of type “Record” and you can click on that Record icon:

You should now see something like the following values, if I hadn’t deleted the username from my List earlier I would see values for all these fields:

If I compare this with the response output from the Flow I triggered with the refresh icon above, I can see that the output really reflects the contents of the “HueResponse” variable:

Lets add these values to the labels I prepared in the PowerApp.

For the label containing the Hue name value, add the following to the Text property: If(HueResponse.access_token="","Hue not Connected!",If(HueResponse.username="","Connection to Hue OK, but User not linked!",HueResponse.name))

This should return something like this:

Proceed to add the following to the Text property for each of the remaining configuration value labels:

HueResponse.ipaddress
HueResponse.apiversion
HueResponse.internet
HueResponse.remoteaccess
HueResponse.devicetype

They won’t show any value in the PowerApp yet though. First we need to get the user registered at the Hue Remote API, which is the next step. Select the following image:

On the Action menu, for the OnSelect event, add the Power Automate Flow for Link and Whitelist User. Change the OnSelect event so that also this is using “Set” function and taking the response from the Flow to the same HueResponse variable, but you also need to supply an input to this flow. For this we will use the HueResponse.access_token, so your OnSelect event should look like this:

Set(HueResponse, 'Hue-LinkandWhitelistUser'.Run(HueResponse.access_token))

Lets test this button. Hold down “ALT” on your keyboard, and click on the image. The Flow should now run, register a user at Hue Remote API, create a new List item and return the configuration to the PowerApp:

Checking the HueResponse record variable now:

A couple of more things remain on the main screen. First, on the App’s OnStart event, add the same event as the refresh icon, this would get the config automatically at start:

Next, select this Image:

On the OnSelect event, add the following:

Launch("https://api.meethue.com/oauth2/auth?clientid=<your_client_id>&response_type=code&state=<youranystring>&appid=<your_app_id>&deviceid=<your_device_id>&devicename=<your device name>")

Replace the <your_…> values with the client id and app id from the Hue Remote API app registration, and your values for device id and name.

Clicking this image will now launch the Hue Developers portal, asking you to Grant permission to the App, and return to the Logic App that retrieves the Bearer Token and store that in the Key Vault as we have seen in previous parts of this blog series.

Summary and Next Steps

We’ve now built the foundation and first part of the PowerApp to retreive the configuration, create and link username, and if needed authorizing and getting a new Bearer Token via Hue Remote API if needed.

In the next part we will build the screen for getting lights and setting lights state and color.

Thanks for reading, see you in the next part!

Blog Series – Power’ing up your Home Office Lights: Part 6 – Using Power Automate Flow to Link Button and Whitelist user

This blog post is part of the Blog Series: Power’ing up your Home Office Lights with Power Platform. See introduction post for links to the other articles in the series:
https://gotoguy.blog/2020/12/02/blog-series—powering-up-your-home-office-lights-using-power-platform—introduction/

In the previous part 5 we created the first Power Automate Flow of the solution, for retreiving the Access Token and getting the configuration of the Hue Bridge via Remote API. To get all the configuration details of the Bridge, we were dependent on that the user had a Whitelist Identifier in the Microsoft List, and this is the Flow we will be working on in this blog post.

Lets do a quick video where I talk about this Flow and what it does:

Create the Flow for Linking and Whitelisting User

Create a new instant Flow, with PowerApps as Trigger. In my case I have named this Flow “Hue – Link and Whitelist User”.

As the first action in the Flow after the PowerApps trigger, add a Compose action:

Tips: Make sure that you set a name for the action, in my case I’ve named it “Access Token”, before you under Dynamic content selects “Ask in PowerApps”. This way the Input parameter will get a more descriptive name like “AccessToken_Inputs”, when we later call the Flow from the PowerApp.

Next, add two Initialize variable actions, called UserDisplayName and UserEmail and type String. For values use the following custom expressions (see comment for expression):

Next, add a Get Items action from SharePoint, and specify your Site and List. For Filter Query, add Title eq ‘<UserDisplayName variable>’:

Add a Condition action, where we will check if the Get Items returns an empty result to be false:

If false, meaning that the user already have a configuration in the List, under “If yes”, add a Get Item action. Specify the Site and List Name, and for Id add the following expression to return the first instance of results first(body('Check_if_User_Already_Linked')?['Value'])?['Id'] :

Next, add a HTTP action where we will query the Hue Remote API for the Bridge configuration details. Specify the URI to be https://api.meethue.com/bridge/<whitelist identifier>/config, and add an Authorization Header with Bearer <Token Outputs>:

This action should return all the details we want from the Hue Bridge, and we can add a Response action to return that back to the PowerApp:

In the other case, when a User Linked was not found in the SharePoint List, we need to add that user and get the Whitelist Identifier. Under “If no”, add a HTTP action. In this action we will “remotely” push the Hue Bridge button via a PUT method. This is basically the same procedure as when you add new lights or equipments, where you need to run and press the button down. But here we do it via the API like below:

PS! Note that above I’ve used “Raw” Authentication and for Value selected Bearer “AccessToken Outputs”. This is just another option to show, I could have have used an Authorization Header instead.

After the Link Button is enabled, we can add another HTTP action, this will register the username via a POST method and a request body containing the “devicetype” value. Device type is so that you can identify the registered usernames on your bridge:

After this action, add a Parse JSON action so that we can more easliy reuse the outputs from adding the username:

For Schema, select “Generate from sample”, and paste the sample output provided by the Hue API documentation here, https://developers.meethue.com/develop/hue-api/7-configuration-api/#create-user, under 7.1.5. Sample Response.

Next, add a “Create Item” action. Specify the Site and List Name, and add the following values for List columns:

Note that for Whitelist Identifier, use the expression body('Parse_JSON')?[0]?['success/username'], this is because the output from Hue API returns an array, so the [0] is to specify the first instance.

Now, using that newly created username, we can query for the Bridge config using the “Whitelist Identifier” from above:

And lastly, add a Response action that returns this back to the PowerApp:

Verify and Test the Flow

That should complete the Flow. We will link that into a PowerApp later, but if you want to you can test the Flow by performing the Trigger action yourself. Then you need to specify a valid Access Token, and the Flow should run successfully, creating a Linked User if you haven’t already:

If you check the List a new item should now represent your user:

Summary and Next Steps

We are now ready to start working on the PowerApp, linking the Flows we have created in this and the previous blog posts. That will come in the next part!

Thanks for reading so far 🙂

Blog Series – Power’ing up your Home Office Lights: Part 5 – Using Power Automate Flow to Get Access Token and Config

This blog post is part of the Blog Series: Power’ing up your Home Office Lights with Power Platform. See introduction post for links to the other articles in the series:
https://gotoguy.blog/2020/12/02/blog-series—powering-up-your-home-office-lights-using-power-platform—introduction/

In previous parts we have built the logic for authorizing and getting Bearer Token for Hue Remote API, and storing that as a Secret in Azure Key Vault, now it’s time to move over to the user side of things. In this part we will build a Power Automate Flow that retreives the Access Token and checks if the user has been set up for configuration. Here is a short video where I walk through that Flow:

Setting up a User State & Config Source

As the PowerApp and Flows we will build are stateless, in the sense it will get data from configured variables and data connections, we need to store some user state and configuration somewhere. The Hue Remote API require that we need to register a so called “whitelist identifer”, a username to be used when sending request to the Hue Remote API, for example: https://api.meethue.com/bridge/<whitelist_identifier>/lights&nbsp;

The way I have built the solution is that the Authorization part, getting, retreiving and if needed refreshing the Bearer Token, are done in the Logic Apps layer, and common for every user that uses the Power Platform solution. On the user side of things, I want every user that share the solution to have their own whitelist identifier.

This means that first time a user use the solution, the user must register their device and retreive the username to be used as the whitelist identifier. Subsequently users will use their own identifer when calling the Hue Remote API.

So we need something set up to store this information about users’ states and configuration, and I have chosen to use a SharePoint List/Microsoft List to do this. This List has been created in a Team where the users of the solution are members.

These are the steps I have done to set it up:

  1. Created a new Team in Microsoft Teams. I’ve named my Team “Elven Hue Lights”
  2. Created a new SharePoint List/Microsoft List in that Team. You can either to this directly in the Team by adding Microsofts Lists to a Tab, and select to create a new List from Blank, or open Lists from the Office 365 launcher. I created a List like this:
  1. Then, in addition to the Title column, add the following columns, single line of text, for storing “Whitelist Identifier” and “Device Type”:

This list will be used by the following Power Automate Flow, so that is the next step to set up.

Create the Flow for Hue Access Token and Config

Create the following Power Automate Flow, of type Instant and using PowerApps as trigger, and using the name “Hue – Get Access Token and Config”:

After the Trigger action for PowerApps, add a HTTP action. This action will send a GET request to the Logic App we created in the previous part “logicapp-hue-get-accesstoken”. So paste the Request Url for that Logic App in the URI field below:

After getting the Access Token from the Logic App, add an Initialize variable to get the calling users Displayname via the triggerOutputs header and x-ms-user-name value:

Next, add a Get Item action from SharePoint, this will retreive any items matching the User Display Name from the List we created for Hue Users. Specify the correct Site Address and List Name, and add a Filter query where Title equals the variable of the User Display Name we got in the previous step:

Next, add a Condition action, where we will evaluate the returned statusCode from the Logic App. This will be either 204 (No Content) or 200 (OK), as we configured back in the Logic App:

If Yes, add a Response action, this will return a JSON response object back to the PowerApp, but in this case it will be empty:

A quick comment on the above Response body, which will be clearer later in the Flow. I’ve prepared a structured response that will possibly return not only the access_token, but also the name (Hue Bridge), and the Bridge IP address, API version etc. But for now, this is empty data.

Let’s move over to the No side of the Condition. Inside “If no”, add another Condition, and name it “If Username is Empty”. This condition should apply if the Get Item action from the List returns no matching user for the display name:

I’m using an expression empty(body('Get_My_Hue_User')?['value']) and if that is equal to the expression true.

Under “If yes”, meaning that the Get Item returns empty results, add another Response action like the following:

In the above case, as we don’t have a matching user configuration stored, we can return the JSON object with only the access_token.

Next, under “If no”, meaning that a matching user was found in the List, add a HTTP action. This action will call the https://api.meethue.com/bridge/<whitelistidentifier>/config, getting the configuration of the Hue Bridge, and using the access_token as Bearer Token in the Authorization Header:

Note! Even though the Get Item action that is filtered for the user display name, in reality will return only one item (or empty), it is still returned as an array of results. So I’m using the expression and function “first” to return only the first item as a single item. So to get the Whitelist Identifier the expression to be used is:

first(body('Get_My_Hue_User')?['Value'])?['WhitelistIdentifier']

After this action, add another Response action, this time returning values for all config values in my custom JSON object:

Ok, quite a few custom expressions used above, so for your convenience I’ll list them here:

body('Get_Hue_Access_Token')?['access_token']
body('Get_Config_Existing')?['name']
body('Get_Config_Existing')?['ipaddress']
body('Get_Config_Existing')?['apiversion']
body('Get_Config_Existing')?['internetservices/internet']
body('Get_Config_Existing')?['internetservices/remoteaccess']
first(body('Get_My_Hue_User')?['Value'])?['WhitelistIdentifier']
first(body('Get_My_Hue_User')?['Value'])?['DeviceType']

That should be this Flow complete.

Test and Validate Flow

We can now validate the Flow using a simple test run. Save the Flow and click on the Test button and “I’ll perform the trigger action”. This should now complete successfully:

As expected the username should be returned as empty as we haven’t yet configured the user for Hue Remote API. So the Flow will return access_token only:

Summary and Next Steps

This Flow will be central later and used on every PowerApp launch to retrieve the access_token and configuration from the Hue Bridge. But first we need to build the Flow for linking User configuration and Whitelist Identifier. That will be in the next part!

Thanks for reading this far, see you in the next part of this blog series.

How I as a Soccer Coach….

…..moved trainings and meetings online using the modern collaboration tools I know and love!

When I’m not working or fulfilling my community activities as MVP, I spend many evenings and weekends at the soccer field, where I’m coaching and managing a soccer team consisting of 14 year old boys.

Due to the Coronavirus situation, as in many countries also Norway has closed it schools, many businesses are either closed or working from home, and in general we are all following the rules of isolating to make sure the virus doesn’t spread. And of course, this has also resulted in closing all grass roots football, for the time being at least to the end of April. I quickly understood that I needed to think in new ways..

So I decided to use the tools I have at hand, and I created virtual follow ups using tools like Microsoft Teams, Forms, Power Automate and SharePoint Online among a few to help support the boys doing self practice and have Virtual team Meetings..

This blog post is a technical version of a LinkedIn article I wrote in Norwegian, https://www.linkedin.com/pulse/hvordan-jeg-som-fotballtrener-jan-vidar-elven/, explaining more the reasons and why I set this up. In this post I will go more into the technical setup, and share some resources for those that want to learn or maybe do something similar themselves. Some of the screenshot images are in Norwegian, but you should be able to understand from my comments.

It all started with Microsoft Teams.. and a Form!

I knew already from before that Microsoft Teams would be more central in my daily work, but I also observed that my son and his classmates, that also plays on the aforementioned soccer team, use Teams themselves now for digital schooling at home. They have daily Teams meetings, as well as some online classes and homework delivery.

So I thought that I wanted to set up a player meeting on Teams, and later a meeting with their parents. This way we could have a social and digital arena to meet each other, as well as talk with the boys how we wanted them to do training with self practice at home. So the first thing was to invite to online meetings.

I knew that the boys already used Teams in school, but I needed to collect their school e-mail addresses. I also suspected several of the parents use Teams at their workplace, but not everyone, so I also needed to get an overview on that. So I decided to create a questionnaire in Microsoft Forms:

How I set it up:

I created a Form with the following inputs:

  • Name (Text). The person filling in the form.
  • Using Teams from before? (Choice). Yes, No and Don’t Know option for parents to answer if they use Teams already.
  • Parents, Teams e-mail address (Text). Their existing Teams work e-mail address or personal e-mail address.
  • Players, Teams e-mail address (Text). The Teams e-mail address they use at school.

In addition I used the club logo and customized the theme colors for the Form. Then I selected Share settings and selected so that “Anyone with the link can respond”. This will mean that all responses are anonymous, so that’s why I require that they type their name in the first input. Then I distributed the Forms link to the parents.

After I received all the responses, I created a Teams meeting invite to the players for the players online meeting, and a Teams meeting invite to the parents for the parents online meeting.

We were now ready for our inaugural online meetings!

Organizing Self Practice Trainings

Normally our soccer team practice at least 3 times a week, in addition to playing games or other activities. So before we had the online player meeting, a self practice training plan was created, focusing on 3 weekly trainings:

  • Conditioning (interval runs, with or without ball, dribbles, jumps and obstacles etc.)
  • Technique, Agility and Strength (ball possession, passing, runs, sprints, physical strength)
  • Endurance (long hikes and outdoor activity with family)

These training should be completed after plan where the boys will get approved attendance for each training they complete. To get a training approved they needed to self register a training form, as well as document by sharing pictures, video, screenshots of activity etc.

The players were shown examples of activities and drills they could complete themselves or with help of family. With this organization and training plan, the only thing that was missing was a system for registering self practice and how I could follow up on that.

I decided to create another Form. In this Form which the boys got a shared link to, they could register their name, date, self assessment, what kind of activity they did and type, provide a description and optionally register number of minutes and kilometres. They were also asked to send in documentation with video, pictures, etc.

This worked really great and next week we already had a lot of responses for completed trainings:

And from the media I received I could really see that the boys were doing their self practice:

How I set it up:

I created a Form with the following inputs:

  • Name (Text). The player name filling in the form.
  • Activity Type (Choice). Conditioning, Technique + Strength, or Endurance.
  • Date of Activity (Date).
  • Self Assessment (Rating). 1-5 stars where they could evaluate their own session.
  • Type of Condition (Choice). If they did conditioning work, what kind of interval (4×4, 60×60, 15×15).
  • Technique + Strength (Text, Long). Comment field for explaining how they did technique and strength work.
  • Endurance (Text, Long). Comment field for explaining what kind of long activity they did.
  • Number of Kilometres (Text, Restricted to Number). Optionally how many kilometres they practiced.
  • Number of Minutes (Text, Restricted to Number). Optionally how many minutes the activity lasted.
  • Sent media of activity (Choice). Yes or No for if they have sent picture, video or screenshot to our team e-mail address.

Also in this Form I used the club logo and customized the theme colors. Then I selected Share settings and selected so that “Anyone with the link can respond”.

PS! I was looking into a File Upload response in the Form, but this cannot be added to a Form that are shared externally. That is why I needed the boys, or their parents, to send their media files to our e-mail address in addition to the Form registration.

Following up on Registered Self Practice Trainings

With all those great responses coming in, I could look through the responses in Office Forms, and download an Excel copy of the responses, but I needed something more to follow up the trainings. So I created a private Team in Microsoft Teams:

Next I wanted to get all the responses from Forms into a SharePoint List. I created the List into the Teams SharePoint Site so that I could get all the registered self practice trainings in one place, and be able to do edits if needed. I also added some extra columns for approve the training and if there was sent media documentation:

Now the only thing I needed was some kind of automation that could bring every response from Forms over to this list: Enter Power Automate!

With the help of Power Automate I created the following Flow to automate that every time a new response is submitted in the Form, this would trigger the Flow:

Next I needed to do some magic on the number inputs, I’ll get back to that in the “How I did it:” section, but the Flow then created a new SharePoint List Item:

How I did it:

The first thing I did was to create the Team that would also host the SharePoint Online Site for my list. The Team was created in my own tenant as a private team, and I elected not to invite any player, or parent, to the Team as guests at this point.

The SharePoint list was created with the following columns to reflect the Form:

  • Renamed Title column to Name
  • Type of Activity (Choice, with the same values as from the Form)
  • Date (Date and Time, Include Time: No)
  • Self Assessment (Number)
  • Type of Fitness/Conditioning Activity (Choice, with same values as from the Form)
  • Technique + Strenght (Multiple Lines of Text)
  • Endurance/Long Actitivty (Multiple Lines of Text)
  • Sent Picture (Yes/No)
  • Number of Km (Number)
  • Number of Mins (Number)
  • Approved (Yes/No)
  • Submitted (Date and Time, Include Time: Yes)

After the list with all the columns was created, the next step was to create the Flow in Power Automate. You can create Flows directly from the SharePoint List, as shown below, and then use one of the provided templates:

Myself I started at https://flow.microsoft.com and selected to create a new Flow as Automated – from blank, and the selecting the trigger for “When a new response is submitted”:

After I give a name to the Flow and select which Form I want to trigger on responses from, I add an Action to get the response details, as shown below:

The next part is a little more complex. When a Form response is submitted, all response details will be provided as Strings. And if I try to update those values directly into the SharePoint list, it will fail because the Column require a number format. So I need to convert those string values to either Integer or Float respectively.

Power Automate have some Data Operation Actions I can use in Flows, and I have used the following three Compose actions, where I get the Self Assessment, Number of Km and Number of Min response details:

The Compose action will create objects I can refer back to later in the Flow. The next complex thing is that I need to check if there are any values for number of kilometers and minutes, and these Form fields are not required and can be empty. There could be several ways to do this, I did it this way:

As shown above, I first add an Action for Initialize Variable, and give it the name for AntallKm (Number of Km), and set the initial value to 0. I specify that the type is Float (as I want to have decimal values). Next I add a Condition action, where I check if the ComposeAntallKm is empty, meaning it is equal to false. I do this as an expression, where the expression is using the empty function and checking against the output from the ComposeAntallKM earlier: empty(outputs(‘ComposeAntallKm’))

If this condition evaluates to false, meaning that there has been provided a value in the Form, then the Flow will go to the If Yes action, and I convert the string to a Float value with the expression: float(outputs(‘ComposeAntallKm’)), I’ve tried to illustrate that with the green arrow below. This expression would have failed the Flow if I didn’t check if it was empty or not. If the value is empty, it would go to the If No action, and this is just empty because I then just let the value be the default 0 i provided when I initialized the variable (illustrated with the red arrow below).

Next in the Flow, I do the exact same logic for the number of minutes:

I’m now ready to update the SharePoint List with a new item. I select the SharePoint Online Create item action, and after specifying the Site and List name, I’ll choose most of the item values from the dynamic content picker. The Km and Minutes values are picked from the respective variable. And for Self Assessment, I do this with an expression consisting of the int function that converts the string to an integer from the Compose action further up.

For reference, my entire Flow at this point is shown below (collapsed without action details):

Take it to the Next Level – Teams Bot with Adaptive Card!

At this point I have a working solution where I get all new responses put in to the SharePoint List. I can now look through, edit and approve the registered trainings.

An even cooler solution would be that each registered training will be posted to the Team Channel as an adaptive card, where I can edit and approve and submit that back so that the list would be updated directly. That way I can follow up and check trainings in my Teams client on either my PC or Mobile, without needing to go to the SharePoint list.

So I added a couple of more steps to my Flow after the Create item action. First I added an action for posting an Adaptive Card to a Teams Channel and wait for a response, the next step was to Update the list item with the values.

I will go into more details later under the “How I did it” section, but the end result of this was that every time a player submits a new training activity, I will get this Adaptive Card in my Teams Channel, summarizing the details of the training and providing me with the ability to edit the player name in case they typed it wrong, update any values for km or minutes, and select yes or no for if the player has sent photos or the training is approved:

When I click the Update button, the values are submitted back to the Flow and the List item is updated.

How I did it:

Before I go into the Flow details on how to post adaptive card to Teams channel and process the response back, I want to show how I built the adaptive card.

Adaptive cards are posted as a JSON formatted message. You can read more about it here https://adaptivecards.io/, see samples and usage scenarios and more. There’s also a great resource called the Adaptive Cards Designer, https://adaptivecards.io/designer/, where you can build your own cards from blank or using one of the sample templates.

The designer lets you add controls and configure properties visually, while producing the JSON message you will need later. This is the design format of the card I ended up with, a little bit of Norwegian text here but you get the main idea, note that I have some placeholder values her, from where I will add data from my Flow later:

In the “Card Payload Editor” window you will see the JSON format you will need use in your Flow, and in the following snippet I’ll provide you with my JSON message for this example here for you to reuse or build on as you like:

{
    "type": "AdaptiveCard",
    "version": "1.0",
    "body": [
        {
            "type": "Image",
            "altText": "Borgen IL",
            "url": "https://borgensawebstorage.z6.web.core.windows.net/borgen_logo.png"
        },
        {
            "type": "TextBlock",
            "size": "Large",
            "weight": "Bolder",
            "id": "Title",
            "text": "Ny Egentrening Registrert!",
            "horizontalAlignment": "Left"
        },
        {
            "type": "TextBlock",
            "text": "Ny egentrening er registrert av <NAVN>.",
            "wrap": true
        },
        {
            "type": "FactSet",
            "facts": [
                {
                    "title": "Type Treningsøkt",
                    "value": ""
                },
                {
                    "title": "Dato",
                    "value": ""
                },
                {
                    "title": "Egenvurdering",
                    "value": ""
                },
                {
                    "title": "Økt beskrivelse",
                    "value": ""
                }
            ]
        },
        {
            "type": "TextBlock",
            "text": "Verifisering",
            "size": "Large",
            "weight": "Bolder",
            "color": "Attention"
        },
        {
            "type": "TextBlock",
            "text": "Verifiser treningsdata og eventuelt oppdater:",
            "size": "Small",
            "weight": "Bolder"
        },
        {
            "type": "TextBlock",
            "text": "Spillernavn",
            "size": "Medium",
            "weight": "Bolder",
            "color": "Attention"
        },
        {
            "type": "Input.Text",
            "value": "",
            "style": "text",
            "isMultiline": false,
            "maxLength": 50,
            "id": "Spillernavn_input"
        },
        {
            "type": "TextBlock",
            "text": "Antall Km",
            "size": "Medium",
            "weight": "Bolder",
            "color": "Attention"
        },
        {
            "type": "Input.Number",
            "value": "",
            "style": "text",
            "isMultiline": false,
            "maxLength": 20,
            "id": "AntallKm_input"
        },
        {
            "type": "TextBlock",
            "text": "Antall Minutter",
            "size": "Medium",
            "weight": "Bolder",
            "color": "Attention"
        },
        {
            "type": "Input.Number",
            "value": "",
            "style": "text",
            "isMultiline": false,
            "maxLength": 20,
            "id": "AntallMin_input"
        },
        {
            "type": "TextBlock",
            "size": "Large",
            "weight": "Bolder",
            "color": "Attention",
            "text": "Godkjenn",
            "horizontalAlignment": "Left"
        },
        {
            "type": "TextBlock",
            "size": "Small",
            "weight": "Bolder",
            "text": "Har spilleren sendt skjermbilde, bilde eller video?",
            "horizontalAlignment": "Left",
            "separator": true
        },
        {
            "type": "Input.ChoiceSet",
            "id": "input_media",
            "value": "1",
            "choices": [
                {
                    "title": "Nei",
                    "value": "false"
                },
                {
                    "title": "Ja",
                    "value": "true"
                }
            ],
            "style": "expanded"
        },
        {
            "type": "TextBlock",
            "size": "Small",
            "weight": "Bolder",
            "text": "Er egentreningen godkjent?",
            "horizontalAlignment": "Left",
            "separator": true
        },
        {
            "type": "Input.ChoiceSet",
            "id": "input_godkjent",
            "value": "1",
            "choices": [
                {
                    "title": "Nei",
                    "value": "false"
                },
                {
                    "title": "Ja",
                    "value": "true"
                }
            ],
            "style": "expanded"
        }
    ],
    "actions": [
        {
            "type": "Action.Submit",
            "title": "Oppdater"
        }
    ],
    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json"
}

With that JSON message ready, I can now add the “Post an Adaptive Card to a Teams Channel and wait for a response” action to my Flow. I select my Team, and the Channel I want to post the adaptive card to, and then paste in the JSON message from the Adaptive Card Designer:


As you can see from the images above, I’ve added dynamic data from the Flow where I had placeholders for values. Note also that I use the values “false” and “true” for the Input.ChoiceSet, this will make it correct when I set the values back to the updated List item.

PS! Another important thing to note is the “id” property of the inputs I want to be able to update back to the Flow. This “id” property needs to be specified later.

The Update message is what will be shown back in Teams after the Adaptive Card has been updated and submitted back with the Action.Submit button. It will look like this:

After the card is updated, a response will be sent back to the Flow. So my next step would be to add a Update item action for updating the selected values in the SharePoint List. From here I will select the SharePoint Site and List Name, and then getting the Id for the existing list item I want to update. This Id is from the earlier action in the Flow from where I created the list item:

The values I want to update back in the List from the Adaptive Card Response is shown above with the blue Teams icon. I will have to specify these by adding an expression that looks like the following, as there are currently no dynamic output from the previous action I can select:

outputs('Post_Adaptive_Card_to_Egentrening_Teams_Channel_Wait_Response')?['body/data/Spillernavn_input']

Note the following from above, refers back to the action name (since I had blank spaces in the step name, I will have to refer back to it with underscore), and from the response body and data section I will refer to the “id” property of the adaptive card input.

Create similar expressions for the other inputs, and that should be it! The complete Flow step is now like this:

Summary and Next Steps

In this quite lengthy blog post I have shown how I built myself a great follow up solution for my soccer team self practice trainings. The boys find it easy to use, and I can use the tools and solutions I know and love for following up. I have also learnt quite a bit of new tricks and tips 😉

I also start to have some great statistics, I can summarize and rank the players so that I can create a top 10 list for example. And these ranks can be published to the boys, they do love a competition and this can motivate them to do some extra work. I have created this HTML table, that I update semi-manually now. I’m already working in the next Flow that will publish updates to this table automatically. So there might be a follow up blog post on this.. 😉

I hope this has been helpful or/and inspiring, reach out to me if you have questions, and remember the Power of the Flow 🙂

Exporting and Importing PowerApps and Flows Package that use a Custom Connector

Just recently I published a blog post on how to use PowerApps and Flow with a custom connector using Microsoft Graph API, to create an app for Azure AD PIM (Privileged Identity Management): https://gotoguy.blog/2018/09/15/create-your-own-azure-ad-pim-app-with-powerapps-and-flow-using-microsoft-graph/.

In this blog post I want to share some instructions and experiences on exporting the PowerApp and Flows to a package, and how you can export the Custom Connector definitions to a swagger file. After that I will show how you in a new environment can import these definitions, and import the PowerApp and Flow package.

Even better, based on the aforementioned blog post on the Azure AD PIM App, I will provide you with download links for the custom connector swagger defininiton for Microsoft Graph, as well as the PowerApp and Flows Package, so you can start from there without having to build all the stuff yourselves Smile!

Export the PowerApps Package

First, start in your Apps gallery of PowerApps, find the Export package (preview) button as shown below:

image

Specify a package name, environment and optionally a description as I have below:

image

Next, review the package content. For the Azure AD PIM App, I’ll change the Import Setup to “Create as new”, the same for the 3 Flows, as shown below:

image

For some of the resources you can select between Create as new or Update, and as I’m planning to import this as a new App with new Flows in the environment, I’ll change this from the default.

image

The other resources (like the connector and connections) I will select during import. This means these will have to be already existing in the environment I want to import the package to.

I can then download the package:

SNAGHTML9abd28

The package is downloaded as a zip file:

image

Inside the zip file there are some manifest json files and the PowerApps and Flows definitions:

image

Export the Custom Connector swagger file

The next thing we want to do is to export the custom connector and its operations. Go to Custom connectors in the menu:

image

Find the “PowerApps Microsoft Graph” connector, and click on the down arrow as shown below. This will download a swagger definition file in JSON format:

SNAGHTMLb16f76

You can open and inspect that JSON file in your favorite JSON editor, here is mine shown in Visual Studio Code:

image

Community Download

Courtesy of gotoguy.blog, I’ll provide you with a download for both the PowerApps/Flows package, as well as the Custom Connector Swagger JSON file. This is helpful if you want to skip right ahead to the next Import section.

These files are placed at my GitHub, in the following repositories:

Import the Custom Connector swagger file

In the new/target environment we will first have to import the swagger file for the Custom Connector. Here you have 2 options:

  1. You can create a new custom connector, and Import from an OpenAPI file/URL:

    image

  2. Or, if you already have a Custom Connector for Microsoft Graph, you can select to Update the existing connector from OpenAPI file/URL:

    image

For sake of education, lets try both variants. The first time you will have to create a new custom connector anyway, but later you will only need to update if there are any changes. I will use OpenAPI URL, as the swagger file is avaiable at my GitHub here: https://raw.githubusercontent.com/skillriver/PowerAppsFlowCustomConnector/master/MicrosoftGraphApi/PowerApps-Microsoft-Graph.swagger.json

PS! Prerequisite

Remember that to be able to use a Custom Connector and Microsoft Graph, you will have to create or use an App Registration in Azure AD in your target enviroment, like I have described in this blog article, under the section “App Registration”: https://gotoguy.blog/2017/12/17/access-microsoft-graph-api-using-custom-connector-in-powerapps-and-flows/.

Take a note of the application ID and secret key:

image

Remember also to give the App the right Microsoft Graph Permissions, and give Admin grant if needed:

image

Import from OpenAPI URL

To create a new custom connector, select to import from OpenAPI URL:

  1. Type a name for the Custom connector, and paste in the URL for the swagger json file:

    image

    Verify the URL and click Continue.

  2. Following that, verify that host is graph.microsoft.com and base URL is “/”, and optionally specify a connector icon, color and description:

    image

  3. On the security page you have to specify the client id which is the app id from the registered app in your target Azure AD environment, as well as client secret and resource URL:

    image
    In my target environment I have pasted in the client id, secret, and the resource URL is https://graph.microsoft.com. Note that the Redirect URL is not available before after the custom connector is saved:

    image

    Click to go to the next Definition page.

  4. At the Definition page, the actions are already in place because they were defined in the OpenAPI swagger file:

    image

    Click “Create connector”.

  5. After the Connector is created and saved, go back to Security, and copy the Redirect URL:

    image

  6. Make sure that the Redirect URL is on the list of the Reply URLs of the Azure AD App Registration:

    image

  7. Back in the Custom Connector, lets test the connector. Go to the Test page and create a connection:

    image

  8. After establishing a connection with your user account, you can go ahead and test one or more of the operations and verify that they run successfully:

    image

After testing this the custom connector is ready to use.

Update from OpenAPI URL

I you want to update an existing custom connector, select to Update from OpenAPI URL:

  1. Provide the URL for the swagger json file:

    image

  2. As with when creating a new custom connector, verify that host is graph.microsoft.com and base URL is “/”, and optionally specify a connector icon, color and description:

    image

  3. When updating an existing connector, you only have to specify the client secret again:

    image

    If you don’t have the original secret stored securely somewhere, you have to go to the App Registration in Azure AD and generate a new one.

  4. Verify that the Operations now has been updated from the imported OpenAPI swagger json file:

    image

    Click Update Connector to save the changes.

  5. After this, go to Test, and either use an existing connection or create a new, and the Test some of the operations to verify:

    image

Now we are ready import the PowerApp and the Flows that will use this custom connector.

Import the PowerApps and Flows Package

We can now import the package we exported earlier, or if you want to use the community download from my GitHub repository, make sure that you download the zip package before this next step.

Start by selecting Import package (preview) from the PowerApps menu:

image

Then browse to the zip packaged to start uploading:

image

When the upload is complete, we can review the package content. We have to select during import the connector and connections, marked as red under here:

image

After selecting the custom connector, and changing the connections to the target environment, we are ready to Import:

image

Note that you also can change the name of the PowerApp and Flows by clicking on the wrench symbol.

Click Import when you are ready, and verify that the import is successful:

image

You can now proceed to open the app for customizations and testing. If prompted, click to Allow the permission request:

image

After opening the Azure AD PIM App, now in the target environment, hold down the ALT key and click Refresh My Roles to test. And you should get the logged on users roles:

image

Obviously, now in the target environment, you would probably start to customize the logo, colors, label texts and language, if you don’t want to proceed with the “Elven” theme 😉

For example something like this from my company:

image

With that I can conclude this blog post, we have been able to export the custom connector definition and the PowerApps package including the Flows, and import these into a new environment. Now all that is left is to publish and share the PowerApp to be used in your organization.

Thanks for reading, hope it has been helpful!

Create your own Azure AD PIM App with PowerApps and Flow using Microsoft Graph

A while back I wrote a blog post on how you could access Microsoft Graph API using a custom connector in PowerApps and Flows: https://gotoguy.blog/2017/12/17/access-microsoft-graph-api-using-custom-connector-in-powerapps-and-flows/.

In this blog article I will build on that blog post to provide a practical example of using Microsoft Graph, and create an Azure AD PIM (Privileged Identity Management) App for activating any eligible admin roles for the logged on user.

First lets look into some of the documentation and what we need to prepare.

Microsoft Graph API for Azure AD PIM

Azure AD Privileged Identity Management provides you a way to enable on-demand time limited access for administrative roles. Microsoft Graph API for Azure AD PIM is currently available under the Beta endpoint, and documented here: https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/resources/privilegedidentitymanagement_root.

If a user that has been assigned admin roles using Azure AD PIM, wants to activate any of the eligible role assignments, the user can navigate to the Azure AD PIM blade or just use this short url: https://aka.ms/myroles. In this blog post I will use my demo user account as an example, and this user has these roles assigned currently:

image

If I want to access my roles using Graph API I can use the privilegedRoleAssignment: my method (https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/api/privilegedroleassignment_my).

Let’s try to do that using the Graph Explorer! (https://aka.ms/GE). Make sure you are signed in using your work account (normal user account), as I have in the screenshot below, and the run the GET command as shown below (https://graph.microsoft.com/beta/privilegedRoleAssignments/my):

SNAGHTML1778e65

In my case this returns the following (I have blurred out my userid for privacy):

image

Note that the response also shows if I have a current activation of any roles, and if so when that will expire. Roles that have isElevated set to “true”, and without an expirationDateTime are roles that are permanently assigned. If I want to query on that I can run the following GET command:

image

When my role assignments are returned I only get roleId’s though, so lets look at how I can get the displaynames of those roles.

For example, I see from the response above that one of the roleId’s returned is 29232cdf-9323-42fd-ade2-1d097af3e4de. In the Graph API for Azure AD PIM there is a method to list privilegedRoles (https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/api/privilegedrole_list), so if I run the following in Graph Explorer: https://graph.microsoft.com/beta/privilegedroles/29232cdf-9323-42fd-ade2-1d097af3e4de, I should get more role information right?

No, I don’t have permission to do that:

image

Lets look at the documentation, and it clearly states that for the requestor (my normal user account) to be able to list privilegedRoles I need to be either a Global Administrator, PIM Administrator, Security Administrator or Security Reader:

image

So that won’t work for me, as I want to let normal user accounts to be able to use my Graph API commands.

However, one thing that normal users do have access to, is listing of directoryRoles (https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/api/directoryrole_list). So if I run that, I will get all directory roles with their id and a roleTemplateId, and I have highlighted below the id I was looking for above, which turns out to be the Exchange Administrator role:

image

So, to get the displayName of the role I can run the following GET request: https://graph.microsoft.com/beta/directoryroles/?$filter=roleTemplateId eq ‘29232cdf-9323-42fd-ade2-1d097af3e4de’:

image

Ok, so now I have a way to query for my role assignments, and also a way to query for the display names of any roles. Now I need to see how I can activate (or deactivate) my role assignments.

I will use these methods: privilegedRole: selfActivate and privilegedRole: selfDeactivate, they are documented at https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/api/privilegedrole_selfactivate / https://developer.microsoft.com/en-us/graph/docs/api-reference/beta/api/privilegedrole_selfdeactivate.

When I do a POST /privilegedRoles/{id}/selfActivate, I need to specify the role id in the request uri and and a request body:

{
  "reason": "reason-value",
  "duration": "duration-value",
  "ticketNumber": "ticketNumber-value",
  "ticketSystem": "ticketSystem-value"
}

For example I can try to activate the Exchange Administrator role by POST to: https://graph.microsoft.com/beta/privilegedRoles/5cfc2572-33b1-4839-8774-2bae31da1a29/selfActivate, and specify a request body like shown below. Note that all properties in the request body are optional, I can just leave them blank or provide default values:

image

Currently there is an error in the Graph Beta API for PIM that won’t let me activate roles that require MFA, so I’ll just accept this error and move on for now:

image

Before I deactivate a role I need to have it to be active, so for now I will go to https://aka.ms/myroles, and activate the Exchange Administrator role manually, promptly requiring MFA verification first:

image

And after that I can activate the role:

image

To deactivate the Exchange Administrator role via Graph API I’ll just do a POST to /privilegedRoles/{id}/selfDeactivate, specifying the role id like this: https://graph.microsoft.com/beta/privilegedRoles/29232cdf-9323-42fd-ade2-1d097af3e4de/selfDeactivate

No request body is needed, and this time I get a successful response:

image

I think these 4 methods will do for now, there are a lot of other methods for managing PIM roles and settings as well, but we are now ready to start working with our PowerApps and Flow Custom Connector.

Add Microsoft Graph Permissions to App Registration

As I mentioned in the beginning of this blog post, I previously wrote a blog post on how to set up an App Registration for a custom connector for PowerApps and Flows. I will now build on this, so if you want to follow the steps I do here, please set up the prerequisites as described in the blog post: https://gotoguy.blog/2017/12/17/access-microsoft-graph-api-using-custom-connector-in-powerapps-and-flows/.

Looking at the documentation I see that I need to add Delegated Permissions for Directory.AccessAsUser.All to be able to list my assignments:

image

Similarly, if I check the documentation for the other methods from above,  I will need also Directory.AccessAsUser.All:

image

image

image

So I will go ahead and add that permission to my App Registration from before. Logged in as a Global Admin find the App Registration, go to Settings and Permissions, and add the following delegated permission for Microsoft Graph:

image

Note that it requires an admin to consent, so remember to click on Grant permissions:

image

Now we are ready to add the PIM API methods to the Custom Connector.

Adding PIM API’s to Custom Connector Operations

Again building on my linked blog post, you should now be able to log on to PowerApps, and find your PowerApps Microsoft Graph connector:

image

If you don’t have it, just follow the steps in the linked post to create it.

Select to edit, and go to step 3. Definition and add a new action. Lets first create a new action for getting my role assignments:

image

Scroll down to Request, this is where we will provide the details for our query. The best way to do this is to select to Import from sample. I specify the Method to be GET, and then the query like this, which is the same query I ran in the Graph Explorer earlier:

image

I don’t need to specify any Header or Body for this query, so I just press Import. Now my action looks like this:

image

Scroll down to the Response section, and then click on the default response. Click on Import from sample, and this time you paste in the response body from the previous Graph Explorer query:

image

This response will help the custom connector operation so that we can get the right output values mapped in our PowerApp later. Select Import.

The response now looks like this:

image

We can also validate that the response looks ok:

image

Click on Update connector to save this operation, do not select to Test at this point. We have more to do..

Next I want to create another action for List directoryRoles. I’ll create a new Action:

image

Request and Import from sample:

image

Note that the Request now will have a $filter parameter:

image

Default Response and Import from sample:

image

Check validation and the Update Connector:

image

Next I want to create another action for

privilegedRole: selfActivate. I’ll create a new Action:

image

Request and Import from sample, this time note the POST verb, and specifying {id} in URL, as well as the request body as shown below:

image

Note now that the request will have an id parameter in the path as well as a body parameter:

image

Default Response and Import from sample (response body is copied from documentation):

image

The response looks like this now and we can check validation:

image

Click Update Connector to save our progress so far. Now we can add the last action for privilegedRole: selfDeactivate :

image

Request and Import from sample, specifying verb POST and again using {id} in URL:

image

The request will look like this now:

image

Default Response and Import from sample:

image

And we can validate the response:

image

Click on Update Connector to save. We should now have 4 actions successfully configured, in addition to the ones we had from before:

image

Now we can do some testing, close the connector for now. Under Data, find Connections. If you previously had any connections to the “PowerApps Microsoft Graph” connector, like I have here, delete the connection:

image

After clearing any existing connections, select New connection at the top and find the PowerApps Microsoft Graph connector:

image

Click create and the log in with your current user to create the connection. Now you can go back to the custom connector, click Edit and then go to Test section. Select the current connection, and select the action to test. Then click Test operation:

image

The test should complete successfully and return my role assignments:

image

Lets test the list directory roles, this time I need to specify the $filter:

image

Testing selfActivate will fail as it did with testing with Graph Explorer because of the MFA requirement: (we will explore that later)

image

image

Last test is for selfDeactivate, which willl have an empty response because the role is not active:

image

Starting with the PowerApp

Now that we have the Custom Connector Operations ready, we can proceed to create the PowerApp. We’ll begin with an empty app, create some controls and layouts before we get into the Flows needed.

Start by Create an app:

image

Then select a blank canvas, and phone layout:

image

You should now have an empty app like this:

image

Fast forward, and I’ll assume you have some basic PowerApps skills, add some controls, layout and image after your liking, ending up with something similar like this:

image

A quick summary of the above:

  • In addition to my selected logo and background, I’ve added labels for listing my roles and selected role details.
  • I’ve added three buttons, one for refreshing my roles, and one for activate and deactivate any roles.
  • I also have a text box to provide an activation reason, as well as a message label to show/hide any error message if I try to activate without a reason. We’ll get to that later.

Now we have an empty powerapp with some layouts and controls. It’s time to get into the Flows that will trigger the Microsoft Graph operations. First go to App Settings and specify an App name and choose a descriptive icon and color:

image

And then save the App:

image

Creating the Flow for Getting My Role Assignments

In the PowerApps main menu, find the link to Flows, and the select to create a Flow from blank:

image

After creating a blank Flow from here there will already be a step for input from PowerApps as shown below:

image

Click New step, add an action, and search for variables, and select the Variables – Initialize variable action:

image

Type the name MyRolesArray and select Type Array:

image

Add a new step of type action, and this time we will search for the custom connector “powerapps microsoft graph”, and that will list any operations we defined earlier. We will now select the operation for “My Privileged Role Assignments”:

image

Our Flow should look like this now:

image

When we tested via Graph Explorer earlier in this blog post, PIM role assignments returned with only role id’s, so we had to do an additional call to list directoryroles to get the displaynames of the roles. We will now implement some logic in the Flow to achieve this.

Add a new step, this time selecting More and Add an apply to each:

image

In the Apply to each, select “value” as output from the previous step as shown below:

image

It’s also a good idea to rename the step, like I have done below before you proceed:

image

Inside the For Each loop, add a new action, searching for the PowerApps Microsoft Graph connector again, this time selecting the List directoryRoles operation:

image

We need to provide a value for the $filter parameter, this is done by typing the filter definition and selecting the roleId from the dynamic content provided by previous step:

image

I also rename the step before I proceed:

image

Next, add another Apply to each section, using the value output from the List directoryRoles to get DisplayName:

image

Next add an action and search for append to array, and select that:

image

Now comes the most important part. I want to use the array variable I initialized in the beginning of the Flow, and build a custom JSON object array which integrates my role assignments as well as the displaynames in one single output. So in the following I select the array variable name, and for value I create my own custom JSON as shown below. In addition I use the dynamic content to search for the values I want to add:

image

At the end of the Flow, outside of the two nested Apply to each loops, add a Request – Response action:

image

In the Response, specify the MyRolesArray as Body, and provide a Response Body JSON Schema. The best way to get a JSON schema is to Save and Test the Flow, and look at the default Response. This is how it looks in my definition:

image

This is the JSON schema I used:

{
"type": "array",
"items": {
"type": "object",
"properties": {
"roleId": {
"type": "string"
},
"displayName": {
"type": "string"
},
"isElevated": {
"type": "boolean"
},
"expirationDateTime": {
"type": "string"
}
},
"required": [
"roleId",
"displayName",
"isElevated",
"expirationDateTime"
]
}
}

Next, Save and Test the Flow. Look for the Test button, and select like below:

image

Follow the on-screen instructions for choosing test connection, and then start the Flow. Click the link to see the Flow run activity, and you should be able to see that the Flow executed successfully and you can look at the details on each step. I’m mostly interested in the Response output at the end, and it looks like this:

image

If I scroll down I can see that the output contains all my roles, and have the display name included in the output. This is the output I eventually will work with in my PowerApp.

Remember to give the Flow a describing name, and Save it before you proceed to the next section.

image

Creating the Flows for Self Activate and Deactivate Roles

Now we need to create the Flows for self activating and deactivating the selected roles. First start by creating a new blank Flow, starting with the input from PowerApps:

image

Add a new step and action for the Microsoft PowerApps Graph connector and the Privileged Role Self Activate operation:

image

When choosing this operation we will get the opportunity to specify input fields, where id is required, as this is the role id for the role we want to activate. In addition we can specify a reason, as well as duration and ticketing info as optional fields:

image

In my solution I want to specify id and reason, and just use the default duration. For the id field and reason field, just click “Ask in PowerApps”, which will create two parameters to use from PowerApps when I will call the flow:

image

In the third step I will add a Request – Response action, and use the Body from the previous step, like this:

image

Save the Flow with a name like I have done below:

image

Then its a good idea to test the Flow, select the test button, provide the trigger for the flow, and when running we need to manually specify the role id to activate, and a reason, like shown below:

(PS! Remember to test with a role that does not require MFA on elevation, because of the previously reported bug.)

image

After clickin Run Now, verify that the Flow successfully started, and then click into the activity details. In the example below I can verify that indeed the role was activated:

image

So that is the Flow for self activating a role, now we need a similar Flow for deactivating a role. Now that we should start getting the hang of this, this is how that Flow should look after creating and saving it:

image

Deactivating a role only requires the role id as a parameter, as shown above. Lets test this as well:

image

The Flow should start successfully, and you can verify the steps like in the following:

image

So, now we have created 3 Flows that we will use in the previously created PowerApp. In the next section we will add the flows and provide some logic to the application.

Connecting the PowerApp to the Flows

Back in the PowerApp created earlier, open it in Edit mode, and select the Refresh My Roles button. Click on the Action menu, and then on Flows, and from the Data section select the Flow we created earlier for Get My Role Assignments:

image

When selecting that Flow, the OnSelect event will populate with the name of the Flow and the Run method. As this Flow doesn’t have any input arguments we can just close the parenthis after like this .Run(), as shown below:

image

So now our button will get any role assignments for the connected user, but we have store the output we get back from the Flow, and use that in the listbox and in the details labels below. So while the Refresh My Roles is still selected, add the following to the OnSelect event:

Set(wait,true);
ClearCollect(MyPIMRoles,GetMyRoleAssignments.Run());
Set(wait,!true)

Like this:

image

A little explanation, the Set(wait,true) and Set(wait,!true) are used at the beginning and end of the action for indicating that the PowerApp is busy when calling the Flow. The ClearCollect is used to store the output response we get back from the Flow in a variable; MyPIMRoles.

Next, set the Items property of the listbox for My Roles to MyPIMRoles:

image

If we now du a test run of the PowerApp, the easiest way to do that is to hold the ALT button down and then click on the Refresh My Roles button. This should return the roles you are assigned to like this:

image

If your listbox is not showing the displayname of the roles, you can change that from the advanced properties of the listbox:

image

While the listbox i still selected, change to the OnSelect method and add the following:

Set(SelectedRole,First(lstMyRoles.SelectedItems))

It should look like this:

image

A quick explanation of this: I’m setting a variable “SelectedRole”, every time I click on a role in the listbox, by getting the first instance of the lstMyRoles.SelectedItems. (In fact, as my listbox only allows to select one item at a time, the first will always be the one I selected).

This “SelectedRole” variable can now be used in my other label details. First, set the lblRoleIdValue.Text property to the following:

image

Likewise, set the lblRoleElevatedValue.Text property to the following:

image

And then set the lblRoleExpiresValue.Text property to: Text(DateTimeValue(SelectedRole.expirationDateTime), DateTimeFormat.ShortDateTime24), like this:

image

As you can see, I’ve added some format functions to display any date and time values from the selected role in the format of short datetime 24 hour clock.

Now, if you hold down the ALT button again, you can click on the selected roles in the listbox, and the labels below will update with the selected role id, if it is elevated or not, and any expiry of existing elevations:

AzureADPIMApp1

Now it’s time to add the other Flows to the Activate and Deactivate buttons, first select the Activate button, and on the Action and Flow menu, select to add the Priviliged Role Self Activate Flow:

image

This Flow needs two inputs:

image

The first input we will get from SelectedRole.roleId, and the second from the txtActivationReason.Text, so it would look like this:

image

Similarly, add the Flow for the Deactivate button, specifying the SelectedRole.roleId as input:

image

Now, at this point we should be able to get my role assignments in the list box, and also to be able to activate or deactivate the selected roles. I do want to add some more logic to the app though. Starting with activating/deactivating the buttons regarding the status of the role. On the Activate button, change the DisplayMode property to:

If(!SelectedRole.isElevated, DisplayMode.Edit, DisplayMode.Disabled)

Like this:

image

And similarly for the DisplayMode property for the Deactivate button:

If(SelectedRole.isElevated, DisplayMode.Edit, DisplayMode.Disabled)

image

Next, I want to add some hint text to the text box for activation reason, this is done this way:

image

At the bottom I have created a label with a message, this lblShowMessage control I want to set visible if I try to activate a role without specifying a reason:

image

Now I need to make some changes to the Activate button and OnSelect method to implement some logic:

image

Lets break that down: First I use the Set method to control wait to indicate that the App is busy, then I do an If check on the txtActivationReason text box, and if I have specified a reason I proceed to run the Flow to self activate the role. After that I clear the txtActivationReason text box, and call the flow for refresh the roles in the list box. At the end I use a ShowMessage variable, setting it to true or false, which in turn is connected to the Visible property of the lblShowMessage control like this:

image

Here is the Activate button OnSelect code for you to copy:

Set(wait,true);
If(!IsBlank(txtActivationReason.Text),
PrivilegedRoleSelfActivate.Run(SelectedRole.roleId,txtActivationReason.Text);
Reset(txtActivationReason);
ClearCollect(MyPIMRoles,GetMyRoleAssignments.Run());
Set(wait,!true),
UpdateContext({ShowMessage: true});
UpdateContext({ShowMessage: false}))

And for the Deactivate button I change the OnSelect to:

image

I don’t need to check the txtActivationReason text box now, so I’ll just clear it and refresh the roles. Here is the code:

Set(wait,true);
PrivilegedRoleSelfDeactivate.Run(SelectedRole.roleId);
Reset(txtActivationReason);
ClearCollect(MyPIMRoles,GetMyRoleAssignments.Run());
Set(wait,!true)

I’ll also add a reset of the activation reason text box to the Refresh My Roles button:

image

And finally, at the OnSelect method of the lstMyRoles listbox, I’ll set the ShowMessage variable to false whenever I click on different roles in the list, so that any previous activation error message is not shown.

image

That should be it! We’ve now implemented some logic to the PowerApp, and are ready to publish and run the App.

Publish and Run the Azure AD PIM App

On the File menu click Save, and the Publish:

image

You can also Share the PowerApp in your organization:

image

(please see my previous blog post https://gotoguy.blog/2017/12/17/access-microsoft-graph-api-using-custom-connector-in-powerapps-and-flows/, and the sharing section at the end for details on the experience on this).

After you have published the PowerApp, you can click the Play button to run the PowerApp. First time you will need to accept permission:

image

After that you should be able to refresh your roles:

image

Let’s try to activate a role:

image

After I click the Activate button, the role will be activated, the list will be refreshed, and I can look at the Device Administrators role that it is now elevated and with an expiry time:

image

The Activate button is now disabled for that role, and the Deactivate button is enabled. Let’s try to deactivate the role again, clicking the Deactivate button. After a short time the role is deactivated, elevation status is false:

image

So now the Azure AD PIM App is working as intended, every user that have been assigned a role can now elevate themselves using the App. Even better is that my users also now can use the mobile PowerApps app to run this from their mobile phones!

As an administrator I can also see the results of the activations in the Directory roles audit history:

image

Known issues and tips

The biggest issue right now is a problem with the Microsoft Graph beta endpoint for selfactivate the role, as it currently does not support activating roles that require MFA. So I you want to use Microsoft Graph for activating roles now, you have to disable the requirement of requiring MFA for activation, either by default for all roles or for roles individually:

image

I’ll keep you posted of any changes to this issue, and update the blog post if that changes.

Another tip is that if you want to do some reporting on how many users are using the PowerApp for activating their PIM roles, you can for example use the ticketSystem string for specifying a constant like below:

image

That should wrap up this blog post, hope this will be useful for you, thanks for reading Smile

Access Microsoft Graph API using Custom Connector in PowerApps and Flows

Microsoft PowerApps and Flows are great and simple to get started and use solutions for creating Apps and for how to “Code with No Code”. And the Microsoft Graph API is a great source of information for your Organizational data, including Users, Devices, Apps and Data. The Microsoft Graph has one common endpoint for which you can access and use all the information you want.

The purpose of this blog post is to show how to set up the requirements for accessing Microsoft Graph from PowerApps and Microsoft Flow.

image

I will show how you create an App Registration in your Azure AD tenant with the required settings and permissions for Microsoft Graph, and how you set up a custom connector in PowerApps and how to connect to that using PowerApps and Flows. We will create a simple App and see how you can share that App in your Organization. Let’s get started!

App Registration

If you want to access the Microsoft Graph you will need an App Registration, for which you can authenticate against the Graph API. There are two options available, depending on whether you want to authenticate only with Azure AD Work or School accounts, or if you also want to authenticate with Microsoft Accounts. The first option is to use the Azure AD portal (https://aad.portal.azure.com), the second option is to use the Application Registration Portal (https://apps.dev.microsoft.com). I will use the Azure AD Portal.

First, login as a Global Administrator to your Azure AD Portal, or have your IT admin perform the following steps for you. Under Azure Active Directory, create a new App Registration:

image

Provide a name like below, select Web app / API type, and then type any URL you want. It doesn’t have to be an accessible URL, as long as it is a valid format:

image

After the App Registration is created, you can open it and note the application id, which we will require later:

image

Next, under Settings, click Required Permissions. Here we will add the permissions we need for accessing the Microsoft Graph.

image

Click Add and then select Microsoft Graph from the list over available APIs:

image

Next, you will need to specify the permissions this App will have to access the Microsoft Graph. Note that there are two types of permissions:

  • Application Permissions. These permissions are for Apps that run without a user logged in, like a service or deamon.
  • Delegated Permissions. These permissions are for running apps in the context of the logged on user. The users effective permission will be a least privilege of these permissions you give the App, and the users actual permission in your organization.

image

In my scenario with using PowerApps and Flows, I will only use Delegated Permissions. Lets start with the most basic permission, and add that to the Microsoft Graph API:

image

Note that there is a column for Require Admin which either contains a Yes or No. If you select a permission that require Admin grant, the Global Administrator must click on the Grant Permissions. In our example now I don’t have to do this, but remember that any time you update the permissions for your app registration that require Admin, you must click on this Grant Permissions button.

image

Next, under Settings for the App Registration, go to Keys. We will now create a secret key to be used together with the application id when authenticating. Type in a description and select a period of expiry, and then click save. Your key will be displayed only once, so make sure you copy it and note it down for later use:

image

We are now ready to head over to PowerApps and create our Custom Connector that will use this App Registration.

Create a Custom Connector in PowerApps

Go to https://web.powerapps.com and log on as your normal user account, you don’t have to be an admin to do this.

Under Custom connectors, select Create Custom Connector, specify a name and continue:

image

On the General page, type a description and optionally change the icon or background color:

image

Under scheme select HTTPS, and under host, specify graph.microsoft.com. The base URL is “/”.

image

Click Continue. Under Security select OAuth 2.0 as authentication type, and then for Identity Provider select Azure Active Directory. For Client id, copy the Application id from the Application Registration we did in the previous section in the Azure AD portal:

image

Scroll down and for Client secret, paste in the secret key you generated from the app registration. Let login URL and tenant ID be as suggested and the type https://graph.microsoft.com as Resource URL:

image

Scroll further down. Scope is optional, and take a note of that Redirect URL will be generated after we save the connector.

image

Click continue to the Definition section. We will get back to this later, so for now just click Create connector:

image

The custom connector will be created, and we can go back and get the redirect URL:

image

Now you need to get back to the application registration in Azure AD and add that Redirect URL to the list of Reply URLs like this:

image

Save that and we are ready for the next step. To summarize, we have now created an App Registration in Azure AD with these 4 steps, as well as prepared a Custom Connector i PowerApps.

image

Now we need to prepare some queries we are going to run in Microsoft Graph.

Prepare queries in Graph Explorer

When working with Microsoft Graph, Graph Explorer is your best friend and resource. You can access the Graph Explorer via the https://graph.microsoft.com website, or even with this simple url:

http://aka.ms/ge

At the Graph Explorer page you can run from a  great collection of samples, and you can either run with a sample account, or log in using your own Work/School or Microsoft account.

image

I will log in as my normal user, and if this is the first time you log in to Graph Explorer you are prompted to consent to permissions needed by the Graph Explorer. From the picture below I have just Run Query for getting my profile:

image

With Microsoft Graph, you can also select just the attributes you want to see, so if I run the following query: https://graph.microsoft.com/v1.0/me/?$select=displayName,givenName,surname,userPrincipalName,aboutMe

I will get this response for my user:

image

From the response I see that my “aboutMe” attribute is empty. Let’s try to put a value into that. This is where the Microsoft Graph documentation is useful. If I look at the API reference for update user, https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/user_update, I see that I will have to use a PATCH method and specify a Request Body which contains the attributes and values I want to update. So for example I will specify my request like this, and then Run Query:

image

I see that the status is success with a status code of 204, and if I check my profile again with the GET query from earlier, I will se that the aboutMe value now has been set: (It’s true by the way, I love working with Microsoft Graph!)

image

Now that we have seen how we can run queries for reading and writing to Microsoft Graph, lets try to implement that in a PowerApp, but first we need to create some Operations for our Custom Connector.

Create Custom Connector Operations

Back in PowerApps and under Custom connectors, I select edit for my connector:

image

I then go to Definition, and since there are no Actions created previously, I will add that now by clicking New Action. This will present me with the following form. I will specify a name, description and an operation id:

image

Scroll down to Request, this is where we will provide the details for our query. The best way to do this is to select to Import from sample. I specify the Method to be GET, and then the query like this, which is the same query I ran in the Graph Explorer earlier:

image

I don’t need to specify any Header or Body for this query, so I just press Import. Now my action looks like this:

image

Scroll down to the Response section, and then click on the default response. Click on Import from sample, and this time you paste in the response body from the previous Graph Explorer query:

image

This response will help the custom connector operation so that we can get the right output values mapped in our PowerApp later. Select Import.

The response now looks like this:

image

We can also validate that the response looks ok:

image

Click on Update connector to save this operation.

Next I want to create another action for updating the aboutMe attribute in my profile. I’ll create a new Action:

image

Under Request I will select Import from sample again, this time specifying PATCH as operation verb, the request URL is https://graph.microsoft.com/v1.0/me, and also add the Headers and Body as shown below. These samples are exactly the same as what I tested in Graph Explorer:

image

As this operation does not return a specific response object, I will let the default response be as it is, and will save my settings by Updating the connector.

Testing the custom connector

In my custom connector I can now move to the Test section:

image

The first thing I need to do is to create a New connection:

image

By logging in with my user I will be presented to consent to the permissions of the App, these are the delegated permissions we configured when registering the App in Azure AD (the reason for the double consent is that in addition to the Microsoft Graph delegated permission, there was also an Active Directory Graph permission for sign in and read profile) :

image

After creating the connection, go back to the custom connector and to the test section again. This time we have a valid connection to choose, and can test the action we want. I will test the GetMyProfile action first:

image

By using the $select parameter I can specify any attribute I want to get, and when clicking Test operation I get a successful response like this:

image

Now, let’s test the second action:

image

I specify the Content-Type to be application/json, and then an updated value for the aboutMe in the profile, and then Test operation:

image

The response is also successful.

Now that the operations are tested and verified, we know that the Custom connector can successfully access the Microsoft Graph, and we are finally ready for creating a PowerApp and testing it all out!

Set up the PowerApp and use the Connector

I will create a PowerApp that will get my profile details, and also be able to update the about me attribute. I will not get into great detail on the general instructions to set up the PowerApp, but the high level steps are:

  • Create a new PowerApp using the blank template and phone layout
  • Add some custom colors and an image (optional)
  • Add some labels and text boxes for getting some chosen profile attributes
  • One of the text boxes is for the “about me” value
  • Create a couple of buttons for getting profile data and to update the “about me” value

So after playing around a little bit I have this PowerApp ready:

image

So lets bring some action into the PowerApp. First, go to the View menu, and then Data Sources. From the list of data sources you should be able to see a connection with your username and the PowerApps Microsoft Graph connector (as I am using PowerApps for other data sources as well, I have a few more):

image

After I add the connection I now have a data source for this Connector:

image

Now I can refer to this data source in my PowerApp, for example in my buttons. I will for the first button add an action for getting my profile data, and for the second button add an action for writing back to “about me” in my profile.

For reading data from my profile, I will add the following action to the OnSelect event:

image

First a little explanation of this action:

  • UpdateContext is a function that would hold data into a variable i specify.
  • Calling the PowerAppsMicrosoftGraph.GetMyProfile operation would return a response I want to save to that variable.
  • Using arguments for $select I can specify which attributes I want to return as a response.
  • So by using UpdateContext and specifying that I save the response back to the MyProfile variable I can use that variable in other controls.

The complete operation is: UpdateContext({MyProfile: PowerAppsMicrosoftGraph.GetMyProfile({‘$select’:”DisplayName,givenName,surname,aboutMe”})})

Then for each textbox control I can get the value from the MyProfile variable, like this:

image

And l would do the same for the other text boxes, using MyProfile.givenName, MyProfile.surname and MyProfile.aboutMe.

Next, for updating the attribute “about me”, I will add the following action to the OnSelect event:

image

In this case I call the PowerAppsMicrosoftGraph.UpdateAboutMeProfile operation, specifying the arguments for content-type and using the text specified in the txtAboutMe.Text property:

PowerAppsMicrosoftGraph.UpdateAbouteMeProfile({‘Content-Type’:”application/json”,aboutMe:txtAboutMe.Text})

Now you can Save, give the PowerApp a Name and a chosen Icon, and then Publish the PowerApp. You are now ready to run the PowerApp!

Running the PowerApp

The PowerApp can be started in different ways, via the mobile app, desktop app or via the https://web.powerapps.com website. When I run this PowerApp I see this after starting up:

image

When I click Read Profile, it will call the Custom connector and get my profile information from Microsoft Graph:

image

Lets update some text in the About me textbox:

image

And then click on the butting Update About me, this will run the PATCH query against Microsoft Graph and update the “about me” attribute.

PS! The operation will run successfully, but it will return the following error when the custom connector to Graph API does not return a response object:

image

This is a flaw in PowerApps using Custom API connector, as it expext a JSON response object, but some operations against API’s are designed to return a 204 No Content response. We will fix that later by using a Flow.

To verify my profile has been updated, I can check in Dvelve and the about me section:

image

At this point we have seen that we can access the Microsoft Graph using a Custom connector from a PowerApp. There are a couple of more scenarios I will show before I wrap up this blog post, using Flows and Sharing the PowerApp with other users in my organization.

Using Microsoft Flow

Using Microsoft Flow with your PowerApps will make it possible to add workflows with actions and condtions to your apps. When creating a custom connector like we did to Microsoft Graph earlier, the same connector is available for your Flows.

I will go to the Flows section and create a new Flow. The first step for getting input from PowerApps is already there, so add a new step and select Action. From there you can search a lot of actions available, and you will find our PowerApps Microsoft Graph connector as well, with it’s 2 defined operations. Select the Update About Me Profile:

image

Next, the operation require 2 inputs, the first one I specify “application/json” which Microsoft Graph expects, and for the next aboutMe input, I select “Ask in PowerApps”:

image

This will create an input I later can use from PowerApps. This is all I need to do now, but I could have added more actions for example for sending an e-mail after updating the profile etc.

Now I specify a Flow name and Create or Update the Flow:

image

Back in my PowerApp, select the Update About me button, and then in the Action menu, select Flows:

image

Then find the Flow I created and add that:

image

You will see that the Run action for the Flow will prompt me for the Input I created with the “Ask in PowerApps” when I edited the Flow. This is where I would supply the the content from the txtAboutMe.Text control:

image

The OnSelect action for this button now looks like this, which will run the Flow:

image

Let’s Save and Publish the PowerApp again, and then launch it. First i Read the profile, and then I update some text in the About me:

image

When running Update About me now, the action successfully completes, with no error warning, and if I go to the Flow I can see the run history shows that it successfully completed. In the details I see that the Flow has triggered with the input I specified in the PowerApp:

image

Note that the Flow handles 204 No Content well, so now we have solved our problem in the PowerApps from earlier 🙂

Using a Flow will not only handle some types of inputs and outputs better for custom connectors than directly from PowerApps, but also make it possible to create more logic to your apps using workflows with actions, conditions and a lot of other data sources.

Sharing the PowerApp with other users

In the last part of this blog post I will show how you can share the PowerApp with other users. When you create a PowerApp it is only you that can access it:

image

Sharing an app that uses a custom connector, like we use for the Microsoft Graph, it will be automatically shared, but users must create their own connections to it.

And when sharing an app that includes a Flow, users who run the app will be prompted to confirm or update any connections on which the flow relies. In addition, only the person who created the flow can customize its parameters.

You can share the PowerApp to specific individuals, to groups or to the whole organization.

image

When sharing to the organization the users can find the PowerApp in the Dynamics 365 app store, under in-house apps:

image

Now, let’s test with another user, in this case I have a test user called [email protected]. When he launches the PowerApp for the first time he will need to create a connection to the custom connector:

image

After signing in he would need to  consent to the App permissions:

image

And after consenting click to Allow:

image

Now he can use the PowerApp, and when clicking Read Profile his details are filled in as expected. This is a test user I have based on the Seinfeild Show, so I will add to the “About me” with some text:

image

When I click Update About me, this users profile is updated. My test user does not have access to see the details of the Flow, but back with my original user that owns the Flow I can see that it indeed ran with the input from this user:

image

Summary

In this blog post we have seen how we can access the Microsoft Graph via a Custom connector in PowerApps and Flows. The sample shown in this post is simple with working with the profile of the logged on user, but with the power of the Microsoft Graph this opens up a lot of possibilities!

In later blog posts I will show some more exciting scenarios for using the Microsoft Graph, and I will link back to this blog post as a reference for how to get it all set up!

Thanks for reading, let me know in the omments if you have any questions or maybe some ideas for usage scenarios!