Monthly Archives: December 2020

Protect Logic Apps with Azure AD OAuth – Part 1 Management Access

Azure Logic Apps are great for creating workflows for your IT automation scenarios. Logic App workflows can be triggered using a variety of sources and events, including schedules, but a popular trigger is using a HTTP trigger for starting the Logic App workflow interactively or on-demand from outside the Logic App.

To trigger a Logic App using a HTTP trigger, you need to know the endpoint URL, for example:

This URL consist of the endpoint address of the Logic App and workflow trigger, and with the following query parameters:

  • api-version
  • sp (specifies permissions for permitted HTTP methods to use)
  • sv (SAS version to use)
  • sig (shared access signature)

Anyone with access to this URL and query parameters kan trigger the Logic App, so it’s very important to protect it from unauthorized access and use.

In this multi part blog post series we will look into how Logic Apps can be protected by Azure AD.

Scenarios this multi-part blog post articles will cover:

  • Provide Management Access Tokens and Restrict Issuer and Audience via OAuth
  • Restrict External Guest User Access
  • Expose Logic App as API
  • Restrict permitted Enterprise Application Users and Groups and Conditional Access policies.
  • Scopes and Roles Authorization in Logic Apps.
  • Logic Apps and APIM (Azure API Management).

Lets first look at the other methods for protecting Logic Apps you should be aware of.

Protect Logic Apps Keys and URLs

Before we move on to protecting Logic Apps with Azure AD Open Authentication (OAuth), lets take a quick summary of other protections you should be aware of:

  • Regenerate access keys. If you have reason to think SAS keys are shared outside your control, you can regenerate and thus making previous SAS keys invalid.
  • Create expiring Callback URLs. If you need to share URLs with people outside your organization or team, you can limit exposure by creating a Callback URL that expire on a certain date and time.
  • Create Callback URL with primary or secondary key. You can select to create the Callback URL with the specified primary or secondary SAS key.

The above methods should be part of any governance and security strategy for protecting Logic Apps that perform privilieged actions or might return sensitive data.

Protect Logic Apps via restricting inbound IP address

Another way to protect Logic Apps is to restrict from where the Logic App can be triggered via inbound IP address restrictions.

This opens up scenarios where you can specify your datacenter IP ranges, or only let other Logic Apps outbound IP addresses call nested Logic Apps, or only allow Azure API management to call Logic App.

Protect Logic Apps with Azure AD OAuth

By creating an Authtorization Policy for your Logic App you can use a Authorization header with a Bearer Token and require that the token contains the specified issuer, audience or other claims. Showing how that works in detail, and usable scenarios will be the main focus for this blog post.

Let’s start by building a basic Logic App we can use for demo purpose.

Creating a basic Logic App with HTTP Trigger and Response

In you Azure Subcription, create a new Logic App, specifying to use a HTTP trigger. In my example below I have named my Logic App “logicapp-test-auth”:

Next, add a Parse JSON action, where the Content is set to the trigger headers, as shown below. I’ve just specified a simple schema output, this can be customized later if needed:

After that activity, add a Response action to return data to the caller. In my example below I return a Status Code of 200 (OK), and set the Content-Type to application/json, and return a simple JSON body of UserAgent where the value is set to the parsed header output from the trigger, using dynamic expression:
body('Parse_JSON_Headers')?['User-Agent']

Testing Logic App with Postman

A great way to test and explore HTTP and REST API calls from your client is to use Postman (Download Postman | Try Postman for Free). When testing the above Logic App, paste in the HTTP POST URL for your trigger, and set the method to POST as shown below:

From the above image, you can see the URL, and also the query parameters listed (api-version, sp, sv, and sig, remember that these should be shared publicly).

When I send the request, it will trigger the Logic App, and should response back:

We can also verify the run history for the Logic App:

We have now successfully tested the Logic App using SAS authentication scheme, and can proceed to adding Azure AD OAuth. First we need to create an Authorization Policy.

Creating an Azure AD Authorization Policy

Under Settings and Authorization for your Logic App, add a new Authorization Policy with your name, and add the Issuer claim for your tenant. Issuer will be either https://sts.windows.net/{your-tenant-id}/ or https://login.microsoftonline.com/{your-tenant-id}/ depending on the version of the Access Token:

We will add more Claims later, but for now we will just test against the Issuer. Before we can test however, we need to get an Access Token. There are several ways to easily get an access token, basically we can consider one of the following two scenarios:

  1. Aquire an Access Token for well known Azure Management Resource Endpoints.
  2. Create an App Registration in Azure AD exposing an API.

We’ll cover App Registration and more advanced scenarios later, but for now we will get an Access Token using well known resource endpoints for Azure management.

PS! Just a quick note on Access Tokens aquired for Microsoft Graph resources: These cannot be used for Logic Apps Azure AD OAuth authorization policies, because Graph access tokens does not allow for signature validation.

Management Access Tokens

The following examples require that you either have installed Azure CLI (Install the Azure CLI | Microsoft Docs) or Az PowerShell (Install Azure PowerShell with PowerShellGet | Microsoft Docs).

Azure CLI

If you haven’t already, you will first need to login to Azure using az login. You can login interactively using default browser which supports modern authentication, including MFA, but if you are running multiple browsers and profiles it might be easier to use the device code flow:

az login --use-device-code

You will be prompted to open the microsoft.com/devicelogin page and enter the supplied device code, and after authentication with your Azure AD account, you will get a list of all subscriptions you have access to.

PS! If your account has access to subscriptions in multiple tenants, you can also specify which tenant to log into using:

az login --tenant elven.onmicrosoft.com --use-device-code

To get an Access Token you can just run az account get-access-token, like the following:

Let’s save that into a variable and get the token:

$accessToken = az account get-access-token | ConvertFrom-Json
$accessToken.accessToken | Clip

The above command copies the Access Token to the Clipboard. Let’s take a look at the token. Open the website jwt.ms or jwt.io, and paste in the token. From the debugger you can look at the decoded token payload. The most interesting part for now is the issuer (iss) and audience (aud), which tells us where the token has been issued from, and to which audience:

As we can see from above, the audience for the token is “management.core.windows.net”. You can also get an access token for a specific resource endpoint using:

$accessToken = az account get-access-token --resource-type arm | ConvertFrom-Json

To show all available resource endpoints use:

az cloud show --query endpoints

Now that we have the method to get the access token using Az Cli, lets take a look at Az PowerShell as well. For reference for az account command and parameters, see docs here: az account | Microsoft Docs

Azure PowerShell

First you need to login to your Azure Subscription by using:

Connect-AzAccount

If your account has access to multiple subscriptions in multiple tenant, you can use the following command to specify tenant:

Connect-AzAccount -Tenant elven.onmicrosoft.com

If there are multiple subscriptions, you might need to specify which subscription to access using Set-AzContext -Subscription <Subscription>. Tip, use Get-AzContext -ListAvailable for listing available subscriptions.

To get an access token using Az PowerShell, use the following command to save to variable and copy to clipboard:

$accessToken = Get-AzAccessToken
$accessToken.Token | Clip

We can once again look at the JWT debugger to verify the token:

As with Az CLI, you can also specify resource endpoint by using the following command in Az PowerShell specifying the resource Url:

$accessToken = Get-AzAccessToken -ResourceUrl 'https://management.core.windows.net'

Now that we have the Access Token for an Azure Management resource endpoint, let’s see how we can use that against the Logic App.

Use Bearer Token in Postman

From the previous test using Postman earlier in this article, go to the Authorization section, and specify Bearer Token, and then Paste the management access token you should still have in your clipboard like the following:

When clicking Send request, observe the following error:

We cannot combine both SAS (Shared Access Signature) and Bearer Token, so we need to adjust the POST URL to the Logic Apps. In Postman, this can be easily done in Postman under Params. Deselect the sp, sv and sig query parameters like the following, which will remove these from the POST URL:

When you now click Send request, you should get a successful response again, provided that tha access token is valid:

Perfect! We have now authorized triggering the Logic App using Azure AD OAuth, based on the Authorization policy:

And the Access Token that match that Issuer:

I will now add the audience to the Authorization Policy as well, so that only Access Tokens for the management endpoint resource can be used:

Any HTTP requests to the Logic App that has a Bearer Token that does not comply with the above Authorization Policy, will received this 403 – Forbidden error:

Test using Bearer Token in Azure CLI

You can trigger HTTP REST methods in Azure CLI using az rest --method .. --url ...

When using az rest an authorization header with bearer token will be automatically added, trying to use the url as resource endpoint (if url is one of the well known resource endpoints). As we will be triggering the Logic App endpoint as url, we need to specify the resource endpoint as well. In my example, I will run the following command for my Logic App:

az rest --method POST --resource 'https://management.core.windows.net/' --url 'https://prod-72.we
steurope.logic.azure.com:443/workflows/2fa8c6d0ed894b50b8aa5af7abc0f08b/triggers/manual/paths/invoke?api-
version=2016-10-01'

From above, I specify the resource endpoint of management.core.windows.net, from which the access token will be aquired for, and for url I specify my Logic App endpoint url, without the sp, sv and sig query parameters. This results in the following response:

So the Logic App triggered successfully, this time returning my console (Windows Terminal using Azure CLI).

Test using Bearer Token in Azure PowerShell

I will also show you how you can do a test using Az PowerShell. Make sure that you get an access token and saving the bearer token to a variable using this command first:

$accessToken = Get-AzAccessToken
$bearerToken = $accessToken.Token

I will also set the Logic App url to a variable for easier access:

$logicAppUrl = 'https://prod-72.westeurope.logic.azure.com:443/workflows/2fa8c6d0ed894b50b8aa5af7abc0f08b/triggers/manual/paths/invoke?api-version=2016-10-01'

There are 2 ways you can use Az PowerShell, either using Windows PowerShell or PowerShell Core.

For Windows PowerShell, use Invoke-RestMethod and add a Headers parameter specifying the Authorization header to use Bearer token:

Invoke-RestMethod -Method Post -Uri $logicAppUrl -Headers @{"Authorization"="Bearer $bearerToken"}

Running this should return this successfully, specifying my Windows PowerShell version (5.1) as User Agent:

For PowerShell Core, Invoke-RestMethod has now support for using OAuth as authentication, but I first need to convert the Bearer Token to a Secure String:

$accessToken = Get-AzAccessToken
$bearerToken = ConvertTo-SecureString ($accessToken.Token) -AsPlainText -Force

Then I can call the Logic App url using:

Invoke-RestMethod -Method Post -Uri $logicAppUrl -Authentication OAuth -Token $bearerToken

This should successfully return the following response, this time the User Agent is my PowerShell Core version (7.1):

Summary so far of Management Access Tokens and Logic Apps

At this point we can summarize the following:

  1. You can trigger your Logic App either by using SAS URL or using Bearer Token in Authorization Header, but not both at the same time.
  2. You can add an Azure AD Authorization Policy to your Logic App that specifies the Issuer and Audience, so that calling clients only can use Bearer Tokens from the specified issuer (tenant id), and audience (resource endpoint).
  3. While you cannot disable use of SAS signatures altogether, you can keep them secret, and periodically rollover, and only share the Logic App url endpoint and trigger path with clients.
  4. This is especially great for automation scenarios where users can use CLI or Azure PowerShell and call your Logic Apps securely using OAuth and Access Tokens.

In the next part we will look more into how we can customize the Logic App to get the details of the Access Token so we can use that in the actions.

Include Authorization Header in Logic Apps

You can include the Authorization header from the OAuth access token in the Logic App. To do this, open the Logic App in code view, and add the operationOptions to IncludeAuthorizatioNHeadersInOutputs for the trigger like this:

        "triggers": {
            "manual": {
                "inputs": {
                    "schema": {}
                },
                "kind": "Http",
                "type": "Request",
                "operationOptions": "IncludeAuthorizationHeadersInOutputs"
            }
        }

For subsequent runs of the Logic App, we can now see that the Authorization Header has been included:

And if we parse the headers output, we can access the Bearer Token:

If we want to decode that Bearer token to get a look into the payload claims, we can achieve that with some custom expression magic. Add a Compose action to the Logic App and use the following custom expression:

Let’s break it down:

  • The Replace function replaces the string ‘Bearer ‘ with blank (including the space after)
  • The Split function splits the token into the header, payload data, and signature parts of the JWT. We are interested in the payload, so refers to that with index [1]
split(replace(body('Parse_JSON_Headers')?['Authorization'], 'Bearer ',''), '.')[1]

Now it becomes a little tricky. We will have to use the base64ToString function to get the payload into readable string, but if the length of the payload isn’t dividable by 4 we will get an error. Therefore we need to see if we need to add padding (=), as explained here: (Base64 – Wikipedia).

First I get the length of the payload data, and then use modulo function to see if there are any remaining data after dividing by 4:

mod(length(outputs('Get_JWT_Payload')),4)

Then I can do a conditional logic, where I use concat to add padding (=) to make it dividable by 4:

if(equals(outputs('Length_and_Modulo'),1),concat(outputs('Get_JWT_Payload'),'==='),if(equals(outputs('Length_and_Modulo'),2),concat(outputs('Get_JWT_Payload'),'=='),if(equals(outputs('Length_and_Modulo'),3),concat(outputs('Get_JWT_Payload'),'='),outputs('Get_JWT_Payload'))))

After this I can use base64ToString to convert to a readable string object and format to JSON object:

json(base64ToString(outputs('Padded_JWT_Payload')))

Now that we have access to the claims, we can later be able to do some authorization in the Logic Apps, for example based on roles or scopes, but we can also get some information on which user that has called the Logic App.

In the Response action, add the following to return the Name claim:

And if I test the Logic App http request again, I can see at it indeed returns my name based on the claims from the access token:

We now have a way to identify users or principals calling the Logic App. The Authorization Policy for the Logic App now permits users and principals from my own organization (based on the issuer claim) and as long as the audience is for management.core.windows.net. But what if I want external access as well? Let’s add to the authorization policies next.

Add OAuth Authorization Policy for Guests

A logic app can have several Azure AD Authorization Policies, so if I want to let external guest users to be allowed to trigger the logic app, I will need to create another authorization policy that allows that issuer:

Lets also add the upn claim to the response, so it is easier to see which user from which tenant that triggered the Logic App:

When I now test with different users, internal to my tenant and external, I can see that it works and the response output is as expected:

Summary of Management Access Scenarios

The purpose of the above steps has been to provide a way for management scenarios, where users and principals can get an Access Token using one of the Azure Management well known endpoints, and provide that when calling the Logic App. The access token is validated using OAuth Authorization Policies, requiring specific issuer (tenant id) and audience (management endpoint). This way we can make sure that we don’t have to share the SAS details which lets users that have access to this URL call the Logic App without authentication.

In the next parts of this blog post articles, we will look into more advanced scenarios where we will expose the Logic App as an API and more.

Blog Series – Power’ing up your Home Office Lights: Part 10 – Subscribe to Graph and Teams Presence to automatically set Hue Lights based on my Teams Presence!

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 last part of the blog series, we will build on the previous blog post where we could get the presence status from Teams to the Hue Power App. Now we will use Microsoft Graph and subscribe to change notifications for presence, so that both the Power App and my Hue Lights will automatically change status based on the presence.

In this blog post I will reuse the Custom Connector I created for managing Microsoft Graph Subscriptions in this previous blog post: Managing Microsoft Graph Change Notifications Subscriptions with Power Platform | GoToGuy Blog

To follow along, you will need at least to create the App Registration and the Custom Connector referred to in that blog post. You can also import the Custom Connector OpenAPI Swagger from this link: <MY GITHUB URL TO HERE>

Adding the Custom Connector to the PowerApp

In the Hue Power App, go to the View menu, and under Data click to “+ Add data source”. Add the MSGraph Subscription Connector as shown below. This way we can refer to this in the Hue Power App.

We are going to add the logic to creating the subscription based on this toggle button and the selected light source:

But before that we have somethings to prepare first. When creating a Graph Subscription, we will need to prepare a Webhook Url for where Graph will send its notifcations when the Teams presence changes. This will be handled in a Power Automate Flow, so lets create that first.

Creating the Flow for Graph Notifications and Hue Lights changes

Since I have built this all before, ref. https://gotoguy.blog/2020/10/24/managing-microsoft-graph-change-notifications-subscriptions-with-power-platform/, I will make a copy of the “Graph Notification – Presence Change” flow for this use case.

If you want to follow along, you will need to follow the instructions in that blog post first. After saving a copy, or if you created a new flow from blank using HTTP request webhook, you will need to copy the HTTP POST URL shown below, as that will be the “notification url” we will refer to later:

Next set some value that only you know for the secret client state:

The next part of the Flow are used to do a first-time validation of adding the change subscription, with Content-Type text/plain and request query containing a validation token. Microsoft Graph expects a response of status code 200 with the validation token back. If that is returned, Microsoft Graph will successfully create the subscription.

For subsequent requests, we must return a 202 Accepted response, and in the next step I parse the notification request body, so that we can look into what change we have been notified for:

Following the change notification, we can start looking into the change value. Firstly, I have added a verification of the secret client state I specified earlier, this is prevent misuse of the notification Url if that become known by others or used in the wrong context. After doing a simple test of the client state, where I do nothing if the client state don’t match, I can start building the logic behind the changes in presence status:

Inside the Switch Presence Status action, I will based on the availability status change, do a different case for each of the possible Teams Presence status values (see blog series post part 9 for explaining the different presence availability values):

Inside each of these cases I will define the light settings and colors, and after that call the Remote Hue API for setting the light. As you saw in part 8 of this blog series, in order to access the Hue API remotely I will need the following:

  • An Access Token to be included as a Bearer token in the Authorization Header
  • A username/whitelist identifier
  • The actual lightnumber to set the state for
  • A request body containing the light state, for example colors, brightness, on/off etc.

Remember, this Flow will be triggered from Microsoft Graph whenever there is a presence state change in Teams. So I need to be able to access/retreive the access token, username and for which lightnumber I created the subscription. This is how I will get it:

  • Access Token will be retreived via the Logic App I created in part 4 of the blog series.
  • Username/whitelist identifier will be retrieved via the SharePoint List i created in part 6, see below image.
  • However, I do need to store the lightnumber I will create the change notification for, and for this I will add a couple more columns in this list:

Customize the Configuration List for storing Subscription Details

I add the following two single-line-of-text columns to my List:

  • Subscribe Presence LightNumber. This will be the chosen Hue light I want to change when change notifications occur for Teams presence status.
  • Change Notification Subscription Id. This will be the Id I can refer back to when adding and removing the subscription when needed.

Customize the Flow for getting User Configuration and preparing Light States

Back to the Flow again, we need to add some actions. First, add a initialize variable action after the initialize SecretClientState action like here:

I set the type to Object and using the json function to create an empty json object. This variable will later be used for changing the light state.

Next, in the Flow after the “Parse Notification Body” action, add a “Get Items” action from SharePoint connector, and configure it to your site, list name and the following Filter Query:

My filter query:
first(body('Parse_Notification_Body')?['value'])?['subscriptionId']
will be used to find what username and light that have been set up for presence changes.

Next, lets set the variable for LigthState. Inside each of the Switch Cases, add the action Set Variable, and then set the variable to the chosen xy color code, as a json object like the following. This is for the color green:

Do the same for all of the other case, these are the values I have been using:

STATECOLORJSON VARIABLE
AwayYellowjson(‘{
“on”: true,
“bri”: 254,
“xy”: [ 0.517102, 0.474840 ],
“transitiontime”: 0
}’)
AvailableGreenjson(‘{
“on”: true,
“bri”: 254,
“xy”: [ 0.358189, 0.556853 ],
“transitiontime”: 0
}’)
AvailableIdleGreen (10% bright)json(‘{
“on”: true,
“bri”: 25,
“xy”: [ 0.358189, 0.556853 ],
“transitiontime”: 0
}’)
BusyRedjson(‘{
“on”: true,
“bri”: 254,
“xy”: [ 0.626564, 0.256591 ],
“transitiontime”: 0
}’)
BusyIdleRed (10% bright)json(‘{
“on”: true,
“bri”: 25,
“xy”: [ 0.626564, 0.256591 ],
“transitiontime”: 0
}’)
BeRightBackYellowjson(‘{
“on”: true,
“bri”: 254,
“xy”: [ 0.517102, 0.474840 ],
“transitiontime”: 0
}’)
DoNotDisturbRedjson(‘{
“on”: true,
“bri”: 254,
“xy”: [ 0.626564, 0.256591 ],
“transitiontime”: 0
}’)
OfflineGrey (10% bright)json(‘{
“on”: true,
“bri”: 25,
“xy”: [ 0.3146, 0.3303 ],
“transitiontime”: 0
}’)
PresenceUnknownWhitejson(‘{
“on”: true,
“bri”: 254,
“xy”: [ 0.3146, 0.3303 ],
“transitiontime”: 0
}’)

PS! The transitiontime is to get as close to realtime updates as possible. Add the colors similarly for rest of the states:

Get the Access Token and call Hue Remote API

Now we are ready to get the Access Token, and call the Hue Remote API with the selected light state.

First, add a HTTP action below the Switch Presence Status action, calling the Logic App previously created in part 4 of the blog series:

Next, add another HTTP request after, and this will call the Hue Remote API to set the lights:

When constructing Hue API URI above, I retreive the whitelist identifier for username with the following expression:

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

And then which light number with this expression:

first(body('Get_My_Hue_User_Subscription')?['Value'])?['SubscribePresenceLightNumber']

That should be the completion of this Flow. Remember to turn it on if needed. We are now ready for the last step.

Adding the Flow for Creating the Graph Subscription

In the beginning of this blog post I referred to the toggle “Sync Hue Lights with Teams” in the Power App. Now that we have prepared the Flow handling the notification Url, we need to add a new Flow that would handle the creating, or deletion, of Graph Subscriptions. As this is a toggle control, setting it to “On” should create a Graph subscription for the selected lights, and setting it to “Off” should remove that subscription again.

Create a new instant Flow with PowerApps as trigger:

Next, add an action for initialize variable for getting the UserDisplayName:

Use the following expression for getting the user display name:

triggerOutputs()['headers']['x-ms-user-name']

Next, add another initialize variable for getting the light number. After renaming the action, click on “Ask in PowerApps”:

Add another initialize variable, this time a boolean value, and for getting the value of the toggle sync control:

Next, we will retrieve our user config source from the SharePoint list again, this time filtered by the UserDisplayName variable:

We now need some logic to the next steps for the flow, lets start by the toogle button which will be either true or false:

If yes, that should mean that we either should create a new graph subscription, or update any exisiting ones.

Under Yes, add a new action. This action will call the Custom Connector I created in another blog post (https://gotoguy.blog/2020/10/24/managing-microsoft-graph-change-notifications-subscriptions-with-power-platform/). This Custom Connector should have the following actions:

Click on the Get Subscription action to add that. For the subscriptionId parameter I will refer to the first returned instance of any exisiting Graph Subscriptions I have in the SharePoint list returned earlier.

Here is the expression for your reference:

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

When running the Flow this action will either:

  • Return a 200 OK if the subscription is found, or if the SharePoint List has a blank value for ChangeNotificationSubscriptionId.
  • Return a 404 ResourceNotFound if the subscription is not found, this will happen if the subscription is expired. This is an error that will halt the Flow, so we need to handle it.

So lets start by getting the Status Code. I’ll do that by adding a compose action with the following expression:

outputs('Get_Graph_Subscription')['statusCode']

It’s also important to set that this action should run even if the Get Graph Subscription action fails:

Lets add another condition, where the outputs of the status code should be 200 (OK):

A status code of 200 will either indicate that either we found an existing Graph Subscription matching the configured subscription id from the SharePoint List, or that the list is blank and the Get Graph Subscription will return an empty array or any other Graph Subscriptions you might have. In the first case, we will just update the existing subscription, in the latter case we will create a new subscription. Lets start by adding another compose action:

Adding the Flow to the Hue Power App

Back in the Hue Power App, we can now link this Flow to the toggle control. With the sync toggle control selected, go to the Action menu, and then click on Power Automate. From there you should see the “Hue – Create Update Remove Graph Subscription” Flow, click to add it. On the OnChange event, add the Run parameters where the lightnumber value is read from the dropdown list and selected items lightnumber, and the toggle button value like this:

Managing Microsoft Graph Change Notifications Subscriptions with Power Platform

In a recent blog post, https://gotoguy.blog/2020/07/12/subscribing-to-teams-presence-with-graph-api-using-power-platform/, I described how you could create a subscription for change notifications for Teams Presence API. In that example, I created a subscription using Graph Explorer. As every subscription has an expiry lifetime, depending on the resource type, you need to have some management over renewing subscriptions before they expire, and re-creating if they have been expired. I also include deleting subscriptions that are no longer needed in that scenario.

In this blog post I’m going to use the Powers of Power Platform to set up this. I’m going to do this from an interactive users’ perspective, using delegated permissions. Many Microsoft Graph API resources supports application permissions, but not all especially those that are in the beta endpoint, so it makes sense for me now to concentrate on delegate permissions.

Lets get started, and as in many scenarios with Microsoft Graph, I will start by creating an App Registration in Azure AD.

Register an App for Managing Graph Subscriptions

Login to your Azure AD Portal (https://aad.portal.azure.com) and go to App Registrations to create a new.

Depending on the settings in your tenant, users can be allowed to create their own application registrations:

If your admin has set this to “No”, you will need to either be a Global Admin, or been added to one of these roles for creating app registrations:

Create the following App registration, just give a name and let the other settings be like default:

Add to the permissions so that you have the following Microsoft Graph delegated permissions:

  • Presence.Read
  • Presence.Read.All
  • User.ReadBasic.All

Note that none of these permissions require admin consent. If you later want to manage subsxcriptions to Graph resources that require admin consent, you will need assistance from your Global Admin to consent to any permissions that require this,

Next, on the Overview page, copy the Application (client) ID, you will need this for later. Next go to Certificates & Secrets, and create a new secret:

Copy this secret for later.

We will now use this app registration as our API to Microsoft Graph, using a Custom Connector in Power Platform.

Create a Custom Connector for Microsoft Graph

Initial creation and authentication

If you haven’t already, log in to flow.microsoft.com, and go to Data and Custom Connectors. The following procedure includes a lot of manual steps, if you want to import this connector and its actions from my swagger definition file, you will find a link at the end of this section.

Select to create a new Custom Connector, from blank. Give it a name, for example:

Provide an optional description, and specify graph.microsoft.com as Host:

Next, under Security, select OAuth 2.0 for Authentication and select Azure Active Directory for Identity Provider. Add the Application Id for the App Registration as Client id, and the Secret you created earlier for Client secret. Type https://graph.microsoft.com as resource, and add under Scope the permissions you added so that the user can consent to these permissions. Type each permission with a space between:

Now, click on Create Connector and verify that is has been successfully created, by now you will see that the Redirect URL field has been updated, copy this value:

Next, go back to your Azure AD App Registration, and under Authentication add a Web platform with the Redirect URI set to the copied value from the Custom Connector.

Lets verify the Custom Connector before we go to the operations. Go to 4. Test, and select to create a New connection:

Next, you will be asked to authenticate with your Azure AD user, note that you will have to consent to the permission scopes we defined for the connector:

And you should successfully have a connection to Microsoft Graph, via the Custom Connector and our App Registration:

Now, we need to add operations via 3. Definition, this where we will call the Microsoft Graph API for queries regarding creating subscriptions and more.

Define Operations for the Connector

Basically this Connector will be doing the same queries like I did by using Graph Explorer in the preceding blog post plus a few more. A pro tip is to use Graph Explorer for sample requests and response when defining operations. In the following I will set up operations for:

  • GET /users/{userUpn}/?$select=id: Get a specific user and id
  • GET /communications/presences/{userId}: Get Presence for a specific user by id
  • POST /subscriptions: Create a new subscription
  • GET /subscriptions: List all my active subscriptions
  • GET /subscriptions/{subscriptionId}: Get a specific subscription
  • PATCH /subscriptions/{subscriptionId}: Update an existing subscription to renew
  • DELETE /subscriptions/{subscriptionId}: Delete a subscription

Get a specific user and id

We will start with the first operation. Go to Definitions and add a new Action. Specify a summary and operation id:

Next under Request, click on Import from sample. Specify a GET query that has the format: https://graph.microsoft.com/v1.0/users/{userUpn}?$select=id, like this and click import:

This will interpret the request URL and recognize that userUpn is a Path parameter variable and $select is a query parameter:

Next, go over to Graph Explorer, and run the same query specifying your own user principal name, copy the response:

Back in the Custom Connector, under Response, click on the default response and click Import from sample. Paste the response you copied from Graph Explorer and click Import:

Click on Update Connector to save this action. You can now go to 4. Test. You can use the connection created earlier, and select which operation you want to test, in this case specify your Upn and to select id to be returned. Testing the operation should be successful:

With the first operation added, lets add the remaining. I will skip the screenshots in the following, just follow the same steps using the information below where I summarize the details.

Get Presence for a specific user by id

Create a new subscription

  • Action Summary: Create Subscription
  • Action Operation Id: CreateSubscription
  • Request Verb: POST
  • Request URL: https://graph.microsoft.com/beta/subscriptions
  • Request Body:
    {
    “changeType”: “updated”,
    “clientState”: “{MySecretClientState}”,
    “notificationUrl”: “{WebhookUrl}”,
    “resource”: “/communications/presences/{UserId}”,
    “expirationDateTime”: “{ExpiryDateTime}”
    }
  • Request Response: (copy example response from running this in Graph Explorer)

List all my active subscriptions

Get a specific subscription

  • Action Summary: Get Subscription
  • Action Operation Id: GetSubscription
  • Request Verb: GET
  • Request URL: https://graph.microsoft.com/beta/subscriptions/{subscriptionId}
  • Request Response: (copy example response from running this in Graph Explorer)

Update an existing subscription to renew

  • Action Summary: Update Subscription
  • Action Operation Id: UpdateSubscription
  • Request Verb: PATCH
  • Request URL: https://graph.microsoft.com/beta/subscriptions/{subscriptionId}
  • Request Body:
    { “expirationDateTime”:”2020-07-14T00:00Z” }
  • Request Response: (copy example response from running this in Graph Explorer)

Delete a subscription

Custom Connector Summary

By now you should have 7 actions defined, remember to test to verify that they work as expected:

NB! Currently I get an error when running GET /subscriptions/{id}, even though it is a correct subscription id and following offical docs: https://docs.microsoft.com/en-us/graph/api/subscription-get?view=graph-rest-beta&tabs=http. I’ll leave the action in the connector but testing it gives me an “internal storage error” both in Graph Explorer and testing with this Custom Connector.

As mentioned earlier, I’ll provide you a link to the complete swagger definition of this connector and its actions here on my GitHub repository:

github.com/JanVidarElven

The Custom Connector can now be used in Power Automate Flows and Power Apps, so in the next section I will start looking into some logic for managing subscriptions.

Choosing a Configuration Source

First we need to look into some kind of configuration source for your Subscriptions to Graph Change Notifications. Consider the following:

  • When you create a subscription, you need somewhere to store the subscription id if you want to be able to update/renew or delete an existing subscription.
  • If you want to continuously renew a subscription, you might want to set an end date for how long you want a subscription to exist.
  • You will want to store the webhook url for where to send the change notifications, and possibly being able to change that if needed.
  • You will want to store the resource/resources you want receive change notifications for and for what type of change.
  • It makes sense to store the clientstate secret so that can be re-used when creating/re-creating subscriptions.

The next question is, where should I store this configuration info? There are some options. If you have access to an Azure subscriptions, you could of course store this in an SQL Database or Cosmos DB to name a few common data stores, or maybe Azure Key Vault for some of the secret info. I want to focus on options typically available for end users though, so it makes sense to go more in the direction of Microsoft 365 services. You could use CDS, Common Data Service, part of the Power Platform and using solutions and custom entities, but that would require admin assistance in either configuring this for you, or giving your end-user permission roles to do this yourself. In addition, CDS will available for all users with access to the environment, so creating a dedicated environment should also be part of that.

In this blog post I will go for the simplest option, I will store it in a list, using SharePoint Online Lists. Another alternative could be to use Microsoft Lists. I will do this by creating a dedicated Teams, and go to the SharePoint Online teams site, and create the list from there.

So I have prepared this now, and my list now contains the following columns, subscriptionId, changeType, clientState, notificationUrl and resource all being field type single line of text, and an endDateTime wit field type of Date with Time:

This will be my configuration store for the following Flows and PowerApps that will mange my subscriptions using the Custom Connector created earlier.

Creating the PowerApp for Managing Subscriptions

My main user interface for managing Graph Subscriptions will be a PowerApp. From this PowerApp I will call actions from the Custom Connector directly, or call Power Automate Flows for where I will have more steps and logic.

Note that this PowerApp can be used to manage all sorts of Microsoft Graph Subscriptions you might have, not just for Team Presence API which is the main focus in this example but for other resources also.

Log in to make.powerapps.com to get started, and follow the general steps in the sections below.

Create a blank canvas app and main screen

Select to create a new Canvas app from blank, give it a name like below, and select format. I will use Table format because I will mainly use this from my PC:

Next in the PowerApps creator studio you can set a Theme for your app, or use your own custom colors and backgrounds. Then you can start adding controls to the canvas. In the below image I have added a custom background, my own logo, some labels for headings and some buttons I will add actions to later. I have also added an icon for later being able to manually refresh.

This main screen will list my active Graph subscriptions on the left part, this will be queried from GET https://graph.microsoft.com/beta/subscriptions. The right part will be from my configuration source, which is the SharePoint list.

It is also a good practice to name the controls using your own naming convention, this is mine for the screen above:

Add Data sources to the Main screen

Next we will start adding the data sources. Go to the View menu, select Data sources, and click “Add data”. Search for “SharePoint” and add the following data source:

Connect with your user, or create a new connection if needed:

Next paste in the SharePoint URL for the SharePoint site where you created the list earlier, and click Connect:

Choose the list:

We now have a data source we can use for this list in the PowerApp:

Next, add a new control to your app, click Insert and under Layout find the “Data table (preview)” control. This will then be placed on your canvas, and you are prompted to select a data source. This is where I select the SharePoint list:

The data table control should now be automatically configured with the fields you created in the list:

To make the data table smaller I will remove some of the fields to display, I’ll remove changeType, clientState and notificationUrl. This leaves me with the following data table which I place under the configured subscriptions part. The list is now empty, but that will be filled in later when I create subscriptions:

Now lets proceed to get the actual Graph subscriptions. Add a new data source, this time search for the name of the Custom Connector we added earlier:

Add that source and choose a connection, and the data source should be added alongside the SharePoint data source:

We will add another Data table control to the Canvas, select Insert and Data table, this time selecting the Custom Connector as data source.

The Items property for the Data table needs to be set as: (MSGraphSubscriptionConnector.GetSubscriptions()).value, which will return a data table for every registered Graph subscription. This should look like this:

After that you can configure the fields to display for the data table, I have added the id, resource and expirationDateTime fields, and placed this data table under the “My Active Graph Subscriptions” part:

I now have the data connections I need for the main screen. The next part is to add actions to the buttons, but before that I will add another screen for where to specify more details for creating a subscription.

Before you proceed, select the main screen from the Tree view and duplicate screen:

I will use this copied screen as starting point for adding the next set of controls.

Creating a Screen for adding new subscriptions

In this screen I have added controls on the left side where you can type in an user principal name, get the user id and get the presence for that user. In this way I can check that I have the correct permissions required for subscribing to change notifications for the specified user.

On the right part of the screen I have added controls for adding a new Graph subscription.

Most of the controls above is label and textbox controls. For User Id and Presence I have change the Display mode to View, and for Notification URL I have changed from single line to multi line.

The change type is a combo box, where I have added to the Items property: [“updated”,”created”,”deleted”]. The expire date time is a date picker control showing date and time in short format.

At the bottom left I have added an icon with a home symbol, and on the OnSelect event for that icon I have added a navigation back to the home screen:

Similarly, on the Home screen I have added a navigation on the “Create Subscription” button to the create subscription screen:

In the next section we will add some actions to the buttons.

Getting User Id and Presence

We will start on the left side of the screen, getting user id and presence for that user. When we created the Custom Connector earlier we created actions just for this scenario.

I will use the UpdateContext function in PowerApps to save the output of the called actions to a variable, and then use that variable for the text input property.

Select the “Get User Id” button, and type the following on the OnSelect event:
UpdateContext({UserId: MSGraphSubscriptionConnector.GetUserIdByUpn(txtUserUpn.Text)})

Like the following:

This will create/update my variable “UserId”, by calling the Custom Connector action GetUserIdByUpn using the input parameter that is the text value from the txtUserUpn text input box. When I click on this button, it will run a query against Microsoft Graph the will return a user record object where I can retreive the .id property.

Next, set the Default propery of the txtUserId text input to UserId.Id:

We can test this right away, click on Preview the App (F5), and type in an existing upn, and press the Get User Id button, it should return the id for your user. You can try several different user upn’s also:

We will do something similar on getting presence. On the OnSelect event for the “Get Presence” button:
UpdateContext({UserPresence: MSGraphSubscriptionConnector.GetPresenceForUser(txtUserId.Text)})

Then set the Default property for the Presence text input to:

When testing you should be able to get the specified users presence by user id.

I’ll add one more thing, on the right side of the screen, for the resource text input, add the following to the Default property:

This will pre-populate the resource based on the user I looked up on the left side, which will come in handy when I create the subscription later:

In the next part I will create the logic behind adding a new subscription, and this will be done using a Flow, as I will have several steps in this logic.

Creating Flow for adding new Graph Subscriptions

This Flow will be triggered from the PowerApp above, and use the Custom Connector action for adding a new Graph Subscription. In the same Flow I will also save the configuration of the subscription to my SharePoint list.

Start by going to flow.microsoft.com, select Create, Start from blank and select Instant flow. Tyoe a name for the Flow, for example “Create Graph Subscription”, and select PowerApps as trigger as shown below:

Next, add the action Initialize variable right after the PowerApps trigger. Set the name of the variable and rename the action to the same. Do this 5 times, as we need input of changeType, resource, clientState, expirationDateTime and notificationUrl. Leave the Default value blank at first.

Pro tip: Make sure that you rename the actions before you do the next step: For each variable, for value select Ask in PowerApps:

The input parameters will now be named nice and recognizable, which will make it easier when calling it from PowerApps:

Before we proceed, we need to convert the date time input from PowerApps to ISO8601 format and UTC timezone, which is expected by Graph API. Additionally subscription expiration can only be 4230 minutes in the future from creation. The thinking behind my PowerApp for adding new graph subscriptions is that the expire date time is sometime in the future including any renewals. So for now I need to create a new variable that can take todays date, add maximum of 4230 minutes, and convert it to ISO8601 UTC format.

Add a new initialize variable action. Give it the following name, set type to string and use the following expression for using now as time and adding 4230 minutes in UTC format: addMinutes(utcNow(),4230), like this:

For the next action, select the MSGraph Subscription Connector, and the Create Subscription action:

You can now add the variables as input parameters to the create subscription action, remember to use the calculated variable for graph expire date time as shown above:

The next step will be to save this configuration to the SharePoint list. Add an action called “Create item” from the SharePoint connector like below. Select the SharePoint site address and the list name for the configuration source created earlier:

Title is required for adding a list item, let’s call the Ask in PowerApps for this one also:

For subscriptionId, select the “id” output from the Create Subscription action:

For the rest of the list values, select the initial variables:

The Flow is now ready to be called. I could have added more error handling and custom response if input data is missing, but I will proceed for now with this.

Calling the Flow from PowerApps

Back in the PowerApp, select the “Add Subscription” button, and on the Action menu select “Power Automate”:

Select the “Create Graph Subscriptions” Flow, which then will be added to the PowerApp, and you are prompted to provide the parameters we defined as “Ask in PowerApps” in the Flow:

Fill in the parameters like below:

Now you can press F5 to preview the app. Type in a UPN, and click to get the User Id. On the right side, make sure that the change type is set to “updated” (if you want to subscribe to presence change) and that the resource is filled in with the correct user id. From the date picker, select any future date, we will later use this date for how long the subscription should be auto-renewed. Last, add the notification URL for the change notifications. Then click on “Add Subscription”, which now should trigger the Flow:

Visually, nothing changes in the PowerApp, so we need to look at the run history for the Flow to see if it ran successfully:

We can also look at the steps that indeed a Graph subscription was created and a list item was added to SharePoint:

While both the Graph subscription and the list has been updated, we need a way to refresh that into the PowerApp. We can use the Refresh(data source) method for the SharePoint list, but that won’t work for the Custom Connector. We will get to that later, let’s start with the SharePoint list. On the refresh icon I added for the main screen, on the OnSelect event, add the following: Refresh(‘Change Notification Subscriptions’);, like this:

If you now preview the app, and click on the refresh button, the right side of the data table should now show a SP list item that has been created (PS! if you have a dark background them, make sure that the data table control has a light background so you can see the text):

Next, for refreshing the Graph subscriptions via the connector, I will change to use a Collection and the ClearCollect method. On the refresh icon, add a new line like this: ClearCollect(GraphSubscriptions,(MSGraphSubscriptionConnector.GetSubscriptions()).value), as shown below:

Next, change the Items property for the left data table for Graph subscriptions to use this Collection:

This should now show the active Graph subscriptions like below:

Now that we have a way to manually refresh these two data tables, using the refresh icon, we can add the same logic to the “Add Subscriptions” button:

The above here in clear text, the set(wait, ..) is a nice way to add busy status to PowerApps when potential long running tasks:

Set(wait,true);
CreateGraphSubcription.Run(dropDownChangeType.SelectedText.Value,txtResource.Text,txtClientState.Text,dateExpireDateTime.SelectedDate,txtNotificationUrl.Text,(txtUserUpn.Text & " Presence"));
Refresh('Change Notification Subscriptions');
ClearCollect(GraphSubscriptions,(MSGraphSubscriptionConnector.GetSubscriptions()).value);
Set(wait,!true)

At this point we have the solution ready for creating Graph Subscriptions and refreshing that in the data tables. Next we need to create Flows for updating and deleting subscriptions.

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.

Blog Series – Power’ing up your Home Office Lights: Part 4 – Using Logic Apps to Get Access Token and Renew Access Token if needed

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/

After building the Logic App in part 3 that will authorize and get access token via Oauth2, we will now create another Logic App that will retrieve the Bearer Token from the Key Vault secret, and renew the Token using Refresh Token whenever it is expired.

Here is a short video where I walk through that Logic App scenario:

Create the Logic App and HTTP Trigger

The first thing you need to do, is to create a new Logic App in your Azure subscription. Select the Resource Group you have contributor access to, and give the Logic App a suitable name, as per your naming guidelines. This is the Logic App I created in my environment:

Add a HTTP request trigger for this Logic App as well:

In the Logic App Designer, make sure you hit Save on the Logic App before the next step. You will now be shown the URL, but first go down to the “Add new parameter” and select Method and GET for method. This way your Logic App will trigger on HTTP GET requests.

Adding Logic App Identity and Key Vault Access

As this Logic App also will request secrets from Key Vault, we will need to add a Managed Service Identity and add that to the Key Vault access policy.

Go to Identity settings, and set the System assigned Identity to On:

Next, go to your Key Vault and under Access policies, add the the newly created Logic App with the following Secret permissions (Get, Set, List):

Add Actions for Getting or Renewing Bearer Token

The actions in this Logic App will retrieve the Bearer Token from the Key Vault and return the Access Token as a Response. If Token is expired, it will be renewed using the Refresh token.

Start by adding a HTTP request, and get the Secret for the Bearer Token like the following:

Next, add a Compose action, getting the outputs from the Get KV Secret Bearer Token action. This secret was stored as a Json Object, but will be returned as a String, so I have used the following custom expression to convert to Json:

json(outputs('Get_KV_Secret_Bearer_Token')?['body/value'])

Next, add the following Compose actions for getting the timestamps in Ticks, and converting to Epoch. See the previous blog post for explanation of why this is necessary, but we need to do this to be able to calculate wether the secret is expired or not:

For your convenience, I’ve added the custom expressions as comments to the actions above, or you can copy it from below:

ticks(utcNow())

ticks('1970-01-01T00:00:00Z')

div(sub(outputs('GetNowTimeStampInTicks'), outputs('Get1970TimestampInTicks')), 10000000)

Next, add a Condition action. Here we will check if the expiry date time of the secret is greater than the current calculated timestamp in Epoch:

Use the following custom expression for getting the “exp” attribute from Key Vault Secret:

outputs('Get_KV_Secret_Bearer_Token')?['body/attributes/exp']

If the secret hasn’t expired, we will return the access token as a Response action as shown below. Note that I will only return the access_token, not the complete Bearer Token stored in the Key Vault secret, as this also contains the refresh_token. The reasoning behind this is that the calling clients (users from PowerApps/Automate) only need the access_token.

As you see from above, I’ve built a Json body and schema for the response, and the custom expression returing the value of access_token is outputs('Compose_Bearer_Token')?['access_token'].

On the False side of the Condition, meaning that the Secret is expired, we will have the logic that renews the Bearer Token. First add two HTTP actions, for getting the Client Id and Client Secret from Key Vault:

Next, add another HTTP action, using Method POST we will send a request to the oauth2/refresh endpoint at Hue Remote API:

The refresh_token need to be sent in a Request Body, using the expression: outputs('Compose_Bearer_Token')?['refresh_token']

Remember to set Content-Type: application/x-www-form-urlencoded. And Authentication Type should be set to Basic, using the retrieved Client Id and Secret from Key Vault as username and password.

Refreshing the Token correctly will return a new Bearer Token. We now need to get and convert the time stamps to Epoch integer, to calulate when the Access Token expires. This is the same process as we used in the Logic App “logicapp-hue-authorize” in part 3 of this blog series. Add 3 new Compose actions like below:

For your convenience, here are the custom expressions used for the above actions:

addSeconds(utcNow(), int(body('Post_Refresh_Code_with_Basic_Auth_to_Update_Access_Token')?['access_token_expires_in']))

ticks(outputs('AccessToken_Expires_Utc'))

div(sub(outputs('GetTimestampInTicks'), outputs('Get1970TimestampInTicks')), 10000000)

Next step is to update the Bearer Token Secret in Key Vault with the new Token we received now and the new expiry date. Add a HTTP action like below:

We can now return the access_token using the HTTP action like below:

The last action we need to add is a default response if any accest_token could not be returned. This is important as we are going to call this Logic App using Power Automate Flows, and we need to have a response for any scenario. Add this after the condition action like below:

For the Null Response action, change the Configure run after setting like the following:

That should be it. Remember to secure outputs for any actions that return credential information:

Verify Logic App

We can now test the Logic App. You can use Postman, Invoke-RestMethod in PowerShell, or just run in the Browser your Logic App Http Trigger Url:

This should return your Access Token:

Looking at the Run History for the Logic App, we should see a sucessful run:

Summary and Next Steps

That should conclude this blog post. In this post, and the previous, we have built the logic behind authorizing and getting the Bearer Token for Philips Hue Remote API, as well as providing and refresh the Token when needed.

In the next part we are going to start building the solution in Power Automate. Thanks for reading, see you in the next part!

Blog Series – Power’ing up your Home Office Lights: Part 3 – Using Logic Apps to Authorize and Get Access Token using Oauth and Hue Remote API

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/

Now that we have registered the application for Hue Remote API, and stored the client Id and Secret in Azure Key Vault, we can start build the Logic App that will authorize and get access token via Oauth2.

Here is a short video where I introduce the concept:

Create the Logic App and HTTP Trigger

The first thing you need to do, is to create a new Logic App in your Azure subscription. Select the Resource Group you have contributor access to, and give the Logic App a suitable name, as per your naming guidelines:

Next, select HTTP request to be the trigger for the Logic App:

After that you will see the following in the Logic App designer:

Make sure you hit Save on the Logic App before the next step. You will now be shown the URL, but first go down to the “Add new parameter” and select Method and GET for method. This way your Logic App will trigger on HTTP GET requests, which is required for the Authorization Code flow with Hue:

Now copy this URL, and make sure that no one but you can access this URL, as this is a SAS (Shared Access Signature) URL that anyone in the world can send requests to if they know the URL. Save the Logic App.

Go back to your App Registration in the Hue Developers Portal, and change your temporary http://localhost/logicapp Callback URL to your Logic App URL:

This means that from now on, the Logic App will handle the authorization code for the Hue App. But first we will need to let the Logic App access the Key Vault.

Adding Logic App Identity and Key Vault Access

For the Logic App, under Settings and Identity, set system assigned managed identity to On:

After this setting is saved, you can later see the status and the object id of the service principal.

Next, under your Key Vault, click on Access Policies and Add Access Policy, from there selec the Get, Set and List Secret Management operations, and for principal search for and add the Logic App. This should look like this after adding:

With permissions in place, we are now ready to add actions to the Logic App.

Add Actions for getting Access Token

The first ting we need to do is to get the authorization code after the Hue App registration redirects back to the callback URL. This is returned as a querystring appended to the URL. Add a “Compose” action and use the following expression for getting the request queries:

(I’ve added the custom expression to comments for better visibility).

Then we need to get the Client Id and Secret from the Kay Vault. Add a HTTP action next, where we will use the Azure Rest API for getting the secret, and authenticate with the Managed Service Identity:

The URI above points to my Azure Key Vault URI, and the specified secret. The documentation for getting secrets can be seen here: Get Secret – Get Secret (Azure Key Vault) | Microsoft Docs.

The same applies to getting the Client Secret, add another HTTP action:

The get an access token from Hue Remote API we must either use Basic Authentication or Digest Authentication. Since I’m running this as a Logic App in a controlled environment and trusting the SSL encryption I will use Basic Authentication. In addition, I will secure the outputs from getting Client Id and Secret from Key Vault, so that other users cannot see those values from the run history:

This setting has been enabled for both the actions getting KV Secret Client Id and Client Secret:

For obtaining an Access Token with Basic Authentication the following header is required: Authorization: Basic <base64(clientid:clientsecret)>

This means that we need to base64 encode the clientid + “:” + clientsecret. This can be done using this lengthy expression, here in a “initialize variable” action:

This above action is just for reference though, as the HTTP action supports base64 encoding out of the box. So when posting to the token endpoint, the best way is to use the following:

(PS! Another way to do Basic Authentication in a HTTP action would be to add the Authorization header manually in the Action above with: “Basic <your calculated base64>” as value, and leaving the Authentication type to None.)

From the above settings, in the URI add the authorization code we got from the request queries earlier, using the expression:

outputs('Compose_Authorization_Code')?['code']

When selecting Authentication type to Basic, the username (client id) and password (secret) will automatically be base64 encoded. The values for username and password are the valies from the Get KV Secret Client actions earlier, in the following format:

body('Get_KV_Secret_Client_Id')?['value']

And this action will return the Bearer Token from Hue Remote API if everything is correctly inputted.

I also make sure that the output of this action is secured from viewing:

With the Bearer Token now retrieved, the next actions is to calculate the expiry time and write the Token back to the Key Vault secret.

Add Actions for getting expiry time and write Token to Key Vault

The Bearer Token returned by Hue Remote API will be in the format of the following masked response:

The _expires_in values are in seconds, so that means that the Access Token is valid for 7 days, and the Refresh Token about 112 days. It would then make sense to only refresh the token when needed.

Lets start by calculating when the access_token expires, with the following expression in a Compose action:

addSeconds(utcNow(), int(body('Post_Auth_Code_with_Basic_Auth_to_Get_Access_Token')?['access_token_expires_in']))

The above expression takes the current time and add the number of seconds for when the access token expires.

This will return a new datetime 7 days ahead. This value will be used to set the expiry time on the Key Vault secret for Bearer Token. By setting an expiry time I can later calculate if I need to refresh the Access Token or not.

But it’s not that easy.. The calculated time above will need to be converted to Epoch (32-bit “Unix”) integer format to be able to set the Key Vault secret “exp” attribute. This isn’t so clear when seeing the API docs, Set Secret – Set Secret (Azure Key Vault) | Microsoft Docs, so took me a little trial and error. And I found great help in this blog article: https://devkimchi.com/2018/11/04/converting-tick-or-epoch-to-timestamp-in-logic-app/.

Based on this I need to convert the timestamp to Ticks (64-bit). Ticks is a built in function in Logic Apps, but to be able to convert to Epoch I will need to calculate the difference in ticks between when the Access Token expire, and the first value of Epoch which is 1970-01-01T00:00:00Z. This is well explained in the above reference blog, but here are my resulting actions.

After calculating the Access Token expiry, I add a compose action which converts this to Ticks:

Using the following expression: ticks(outputs('AccessToken_Expires_Utc'))

Then I need to find the 1970-01-01T00:00:00Z value in Ticks:

Using this expression: ticks('1970-01-01T00:00:00Z')

Then we can convert this to Epoch by subtracting the two Ticks values calculated above, and divide by 1 million:

This is the expression used above: div(sub(outputs('GetTimestampInTicks'), outputs('Get1970TimestampInTicks')), 10000000)

We now have the correct format for the “exp” attribute to update the Key Vault secret. Add a new HTTP action and configure like below:

Remember to secure the Output for this action also:

Finally we can finish this Logic App by adding a Response action and do a quick test to verify that everything works as expected.

Adding Response action and verify Logic App

Add a Response action with status code 200 and a body like below:

Tips: It can be difficult to troubleshoot the Logic App when securing outputs, so you might hold back in that when testing. It will show your secrets in the run history though, so it might be best to do this in a test enviroment depending on your needs.

Now we can test. Construct the URL for authorizing the App again, like we did in Part 1:

https://api.meethue.com/oauth2/auth?clientid=&response_type=code&state=elvenanystring&appid=elven_demo_hue_app&deviceid=elven_demo&devicename=Elven Demo

Paste it in the Browser, and after granting access to the App in Hue Developer portal:

You should be redirected to the Logic App:

.. and with a respons success!

Looking at the Run history, we can verify the steps were successful:

You can also look into the inputs and outputs of the actions, except the actions where we secured the output:

We can also verify that the Key Vault secret storing the Bearer Token has been updated and have an Expiration Date one week forward:

Summary and next steps

That concludes this blog post. Thanks for reading this far, in the next part we will build the Logic App that will respond back the Access Token and renew using Refresh Token if needed.