Category Archives: Microsoft Graph

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!

Subscribing to Teams Presence with Graph API using Power Platform

Since the support for getting Teams Presence via Microsoft Graph API came into public preview earlier this year, https://docs.microsoft.com/en-us/graph/api/presence-get?view=graph-rest-beta&tabs=http, many where seeing interesting scenarios for automating Microsoft 365 using this presence status. In fact many, myself included, created different solutions for setting light bulbs etc to reflect the Teams presence. If busy, then red lights, if available green lights, and so on. I have this setup myself using Philips Hue lights, and have created a PowerApp using Flows to control my lights:

There has been one problem though, getting Teams Presence has only been possible by continuously querying the API to check if the status has changed. This can be scheduled of course, but running this every minute or so seems like an excessive way to achieve the goal: being able to see if the Teams Presence has changed!

Until just a few days ago that is, where I noticed that Teams Presence now is in Preview for subscribing to change notifications in Microsoft Graph: https://docs.microsoft.com/en-us/graph/webhooks#supported-resources

In this blog post I wlll show how to create a subscription for change notifications for Teams Presence for a specified user, and the requirements for doing this. And I will use Power Platform and Power Automate Flows to achieve this.

Let’s start with the Requirements..

First of all, to be able to set up a change notification for a resource, you need the same API permission as the resource require itself, for Teams Presence this is one of the following:

  • Presence.Read, for being able to read your own users presence status.
  • Presence.Read.All, for being able to read all users in your organization’s presence status.

Currently in the Beta endpoint, getting presence is only supported for Delegated permissions using work account, so you will have to to this with a logged in user.

The other important requirement is that you need a webhook uri for where the change notification can send a POST request for the resource that has been changed. This webhook uri can be on your preferred platform, many are using Azure Functions for this, but it can also be a third party platform. I will do it using Power Automate, another alternative could be using Azure Logic Apps also.

This webhook uri need to be able to:

  • Process the initial creation of the change notification subscription. Microsoft Graph expects a text response with a validation token for it to be successful.
  • Process every change to the resource that you subscribe to, in this example a Teams Users Presence Status.

We will get into the details on this, but for now, we will start explore using Graph Explorer.

Explore Presence and Subscriptions with Graph Explorer

Go to the Microsoft Graph Docs site and find Graph Explorer there, or just go to https://aka.ms/ge, and log in with your work account.

Type the following GET query: https://graph.microsoft.com/beta/me/presence

You need to be a Teams user to run this, but if permissions are consented, you should be able to see your own presence status like my example below. If you are getting a permission error, make sure that one of the permissions for Presence.Read or Presence.Read.All er consented. This can already been done by your administrator, if not you need to consent to them yourself.

Great, let’s check another users’ presence status. PS! The permissions don’t require admin consent, and using delegated permissions every user can check other users presence status, but you need Presence.Read.All to do that.

You need the other users id property, so you can check that first using for example <a href=”https://graph.microsoft.com/v1.0/users/https://graph.microsoft.com/v1.0/users/<someotherusersUpn>/?$select=id.

And then query for the other user’s presence: <a href=”https://graph.microsoft.com/beta/users/https://graph.microsoft.com/beta/users/<userid>/presence

Another way to query for your or other users presences, that are more aligned to the change notifications is using the /beta/communications/presences endpoint: <a href=”https://graph.microsoft.com/beta/communications/presences/https://graph.microsoft.com/beta/communications/presences/<userid&gt;:

If you can run all these queries successfully, then you are ready to proceed to change notifications subscriptions.

You can check if you have any active subscriptions for change notifications using a GET query to: https://graph.microsoft.com/v1.0/subscriptions or https://graph.microsoft.com/beta/subscriptions, depending on if you are working with preview resources. If you have no active subscriptions this should return a successful but empty response like below:

The next part would be to create a subscription for change notifications for presence, but first we need to prepare the Flow for receiving the webhook uri.

Create a Power Automate Flow for Change Notification Webhook

Log in with your work account to flow.microsoft.com, and create a new flow of type automated and blank, skip the first part of using pre-selected triggers. Search for the Request type trigger that is called “When a HTTP request is received”:

Next add a Initialize Variable action for setting the ClientState which we will use later for the creating the subscription. Set the variable to anything you want, give a name to the Flow and then save. When saved the HTTP POST URL will show the value you later will use as the webhook uri for the change notifications:

The next part is the most important one, and that require a little knowledge of the creation process for change notifications subscriptions. This is documented here https://docs.microsoft.com/en-us/graph/webhooks#managing-subscriptions, but the high level steps are:

  1. When the Subscription is created, a POST request is sent with Content-Type text/plain and a query parameter that contains a validationToken. Microsoft Graph expects a 200 OK response and a text/plain body that contains the validationToken to be able to successfully create the subscription.
  2. Immediately after creation, and for every change notification, a POST request is sent with Content-Type application/json. Microsoft Graph expects a 202 Accepted response to this, if not it will continuously try to send the same change notification. You should also check the ClientState for verification, and of course include your own business logic for what to do in the Flow for when changes occur.

So your Flow needs to address these requirements, and there can be different ways to achieve this, but this is how I did it in my setup:

After the initialize variable, I created a Switch control action, using Content-Type from the HTTP Request trigger. In this way I can separate the logic in my flow for the initial creation and validation, and for the updates.

Validating the Subscription

If the Content-Type is text/plain; charset=utf-8, I will try to get the validation token sent by Microsoft Graph, and create a response that returns status 200 OK and the validation token back in a text/plain body.

I used the Compose data operation, and a custom expression that retrieves the validationToken from the query parameters. The expression I use is: @triggerOutputs()[‘queries’][‘validationToken’].

The Request Response action returns a status code of 200, set the Content-Type to text/plain and for Body select the Output from the Compose Validation Token.

The above steps should be sufficient for creating the subscription, it is recommended to validate the ClientState also, in my case I have done that in the next step.

Processing and Responding to Change Notifications

The change notifications will come as Content-Type “application/json; charset=utf-8”, so I add a case for that under my Switch. Microsoft Graph expects a 202 Accepted Response, it is recommended to respond this early in your flow, so that any later actions or your own business logic generates errors that prevents this response.

In the Response action I just return 202 Accepted. I have then added a Parse Json action to make it easier to reference the values later in the flow:

You can generate the schema from an existing sample, from the Microsoft Graph docs, referred above, or you can just use the following sample from me here:

{  “value”: [    
{      “subscriptionId”: “<subscriptionid>”,      
“clientState”: “MyGraphExplorerSecretClientState”,      
“changeType”: “updated”,      
“resource”: “communications/presences(‘<userid>’)”,      
“subscriptionExpirationDateTime”: “2020-07-11T20:04:40.9743268+00:00”,      
“resourceData”: {        
“@odata.type”: “#Microsoft.Graph.presence”,        
“@odata.id”: “communications/presences(‘<userid>’)”,        
“id”: null,        
“activity”: “Away”,        
“availability”: “Away”      },      
“tenantId”: “<tenantid>”    }  
]}

Now I can begin my business logic. As the value from the notification body is of type array, an Apply to each block will be needed, it will be automatically added if you select any of the attributes in the resulting actions. I will first verify that the clientState is matching the variable i defined in the beginning of the flow. This is a safestep that only the Graph subscription I created can call this Flow.

In the next part I have added a new Switch control, where I retrieve the presence status that have changed.

And this is where you add your own business logic, so I will stop here. In my own example (see PowerApp for Hue Lights above) I will control my lights based on presence updates, but this is a theme for a upcoming blog post.

With the Flow ready, we can now create the Subscription.

Creating Microsoft Graph Change Notification for Teams Presence

I will now create the Subscription in Graph Explorer, using a POST request to https://graph.microsoft.com/beta/subscriptions. In this POST request you will need a request body that contains the following:

Here is a quick explanation of the above values:

  • changeType: can be “updated”, “created”, “deleted”. Only “updated” is relevant for presence changes.
  • clientState: For verification in the webhook that the call is coming from the expected source, consider this a sensitive value.
  • notificationUrl: This is the webhook uri, and for my Flow this will be HTTP POST URL shown earlier.
  • resource: This is the user I want to get presence updates from. Note that you can get multiple user presences also using /communications/presences?$filter=id in ({id},{id}…) (https://docs.microsoft.com/en-us/graph/api/resources/webhooks?view=graph-rest-beta)
  • expirationDateTime: Every subscription only lasts for a specific time depending on resource type. The subscription needs to be renewed before expiry. For Teams Presence subscriptions only last one hour, same as chatMessage. See details for different types of resources: https://docs.microsoft.com/en-us/graph/api/resources/subscription?view=graph-rest-beta#properties. If you select an expiry time that is larger than supported, it will reset to one hour max.

Let’s run this query to create the subscription, if everything works, I will now get a 201 response that the subscription is created. Note the expiration time that is one hour from now:

This wouldn’t work if my Flow had failed, so let’s look into the run history on that. I see that I have 2 recent successful runs:

Let’s look into the first one. I see that the request is coming in as a text/plain with a validationToken, which I then return to Microsoft Graph:

Let’s look into the second run. This returns the first presence update, I can see that the user is “away”:

Now, let’s test this. With my user I go to Teams client, it should automatically change my presence from away to available or busy depending on my calendar, or I can set the status manually myself:

Checking the Flow runs again, I can indeed see that the Flow has been triggered via the Change Notification:

If I look into the details, the status update is Available:

If I bring up the Flow in a bigger picture I can indeed see that my logic ends up where the switch case checks for available status:

My Flow will now be triggered for every change as long as the subscription don’t expire.

Summary

In this blog post I have shown how you can create a Microsoft Graph Subscription for Change Notifications to selected users Teams Presence, using Power Automate to validate subscriptions and process the changes.

There are more work to do, as I need some logic for renewing and managing my subscriptions. But that will be the topic for the next blog post coming soon!

Thanks for reading, hope it has been useful 🙂

Oauth Authentication to Microsoft Graph with PowerShell Core

In this short blog post I will show you a really simple way to get started authenticating with Oauth to Microsoft Graph using PowerShell Core.

As you might know, PowerShell Core is the open-source, cross-platform (Windows, macOS, and Linux) edition of PowerShell, with the latest version today being PowerShell 7.0 ( https://docs.microsoft.com/en-us/powershell/scripting/whats-new/what-s-new-in-powershell-70?view=powershell-7). The latest version of Windows PowerShell is 5.1, and runs side-by-side with PowerShell Core.

I’ve been using Windows PowerShell mostly previously, as I’m running Windows 10 and use a lot of PowerShell modules that variously depend on SDKs or other Windows Components, but I’m increasingly using PowerShell Core in scenarios for example with Azure Functions PowerShell ( https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference-powershell). My computer now runs Visual Studio Code and Windows Terminal with different Profiles, so that I can easily change between environments and run side-by-side:

This blog post isn’t about the details of PowerShell though, so lets get back to the topic at hand. When running PowerShell against Microsoft Graph you would run requests using the command Invoke-RestMethod. The thing that caught my attention was the added parameters of specifying Authentication and Token with the request: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-restmethod?view=powershell-7#parameters.

Let’s compare the “old” way and the “new” way, but first lets get an Access Token for Microsoft Graph.

Get Access Token using Graph Explorer

If you want to learn Microsoft Graph and start with some sample queries, Graph Explorer should be your main starting point: https://developer.microsoft.com/en-us/graph/graph-explorer/preview. The new preview version of the Graph Explorer lets you get a copy of your Access Token if you sign in with your account as shown below, you can copy it to your clipboard:

This Access Token will run queries as the logged on user (yourself) using the consented permissions in Graph Explorer, so you should only use this token for your own sample queries and not share it with anyone else.

Preferably you would get an Access Token by registering your own App Registration in Azure AD and authenticate using one of the following authentication flows:

  • Authorization Code Flow (Delegated User – Web Apps and APIs)
  • Device Code Flow (Delegated User – Native Clients, recommended for PowerShell)
  • Client Credentials Flow (Application Permissions – Scripts and Background Processes that don’t require user interactivity)

But for now I would use use the Access Token from Graph Explorer for the following samples.

The “old” way, using Authorization Header with Bearer Token

This method works with both Windows PowerShell and PowerShell Core. After aquiring an Access Token you would need to specify an Authorization Header with a Bearer Token for every request. In this example I get the Access Token from the Clipboard, as I copied that from the Graph Explorer.

$accessToken = Get-Clipboard
Invoke-RestMethod -Method Get -Uri "https://graph.microsoft.com/v1.0/me" -Headers @{"Authorization"="Bearer $accessToken"}

This should return a response like below:

The “new” way, using Authentication and Token Parameters

This method only works on PowerShell Core. The Access Token needs to be a secure string, so you need to convert it first like the following:

$accessToken = ConvertTo-SecureString (Get-Clipboard) -AsPlainText -Force

Another way would be to prompt for the Access Token and paste it with the following command:

$accessToken = Read-Host -AsSecureString -Prompt "Enter/Paste Oauth2 Token"

And then you would run the request specifying the Authentication parameter to be Oauth, and the Token parameter to be the secure string:

Invoke-RestMethod -Method Get -Uri "https://graph.microsoft.com/v1.0/me" -Authentication OAuth -Token $accessToken

This should return a response like below:

Summary

So in summary you can start using the Authentication and Token parameters in PowerShell Core, it would add / override the Authorization Header and Bearer Token for you. There can also be some added security gains as the Token is submitted as a securestring, which means you can try to keep it out of code as clear text.

How to Use Azure AD Privileged Identity Management PowerShell and Graph API

A while back I wrote a blog post on how you could download, install and use a separate Azure AD PIM PowerShell Module for managing Privileged Roles, https://gotoguy.blog/2018/05/22/getting-started-with-azure-ad-pim-powershell-module/. With the recent update of the AzureADPreview Module, the cmdlets for managing Privileged Roles are now included in the module, so there is no longer required to install a separate module for this!

In this blog post I will explain and show how these commands can be used. These PowerShell CmdLets are also at parity with the Graph API, so I will also show equivalent methods for this.

Install or Update AzureADPreview Module

First you need to either install or update the AzureADPreview Module, so that you are running on version 2.0.2.27 or newer.

Update November 23 2020: Latest version of AzureADPreview Module is 2.0.2.129.

The AzureADPreview Module can be installed from PowerShellGallery using Install-Module or Update-Module, and you can verify which version you have installed using Get-Module <modulename> –ListAvailable like this:

image

With that requirement out of the way we can proceed to look at the commands.

Privileged Role Management Commands

Currently in the AzureADPreview Module, there are 13 commands related to Privileged Roles:

Get-Command -Module AzureADPreview | Where-Object {$_.Name -like “*privileged*”}

image

The new cmdlets in AzureADPreview Module related to PIM are documented here, https://docs.microsoft.com/en-us/powershell/module/azuread/?view=azureadps-2.0-preview#privileged_role_management.

Note that some of the above commands are not in that documentation, all the new commands have a *MS* which means it is mapped to equivalent Microsoft Graph API’s.

In the interest of this blog post, here is a quick explanation of each of the available commands:

  • Add-AzureADMSPrivilegedResource. Use this API to add a new azure AD MS privileged resource.
  • Close-AzureADMSPrivilegedRoleAssignmentRequest. Cancel a AzureADMSPrivilegedRoleAssignmentRequest.
  • Get-AzureADMSPrivilegedResource. Get azure AD MS privileged resource.
  • Get-AzureADMSPrivilegedRoleAssignment. Get role assignments for a specific provider and resource.
  • Get-AzureADMSPrivilegedRoleAssignmentRequest. Get role assignment request for a specific resource.
  • Get-AzureADMSPrivilegedRoleDefinition. Get role definitions.
  • Get-AzureADMSPrivilegedRoleSetting. Get role settings.
  • Open-AzureADMSPrivilegedRoleAssignmentRequest. Create a role assignment request.
  • Set-AzureADMSPrivilegedRoleAssignmentRequest. Update a role assignment request.
  • Set-AzureADMSPrivilegedRoleSetting. Update role setting.

The other 3 Privileged Role commands that are still available to use, but currently are not documented on the above link to docs are:

  • Get-AzureADPrivilegedRole. List all Directory Roles available for Privileged Roles assignments.
  • Get-AzureADPrivilegedRoleAssignment. List active and eligible privileged role assignments.
  • New-AzureADPrivilegedRoleAssignment. Creates a new privileged role assignment for specified role and user.

(*) As soon as your tenant is upgraded to using the updated Privileged Identity Management experience for Azure AD roles (see below) these three commands will be outdated and should not be used anymore.

Further on in this blog post I will provide some more examples and usage scenarios for the new Azure AD Privileged Role Management commands, and their equivalent Microsoft Graph API methods, but first something on the difference between Azure Resources and Azure AD, changes in management experience and current limitations in the PowerShell commands.

Azure Resources vs. Azure AD

As you might know, Azure AD PIM can be used for managing privileged role assignments to both Azure AD roles and Azure Resources:

image

The new PowerShell commands that follows the syntax verb-AzureADMSPrivilegedRole…. all require a parameter called ProviderId, which as per today only support “AzureResources”. This means that currently you can only use the new Azure AD PowerShell commands for managing PIM for Azure resources, not for Azure AD roles yet! I had this confirmed with the Microsoft Program Manager for Azure AD PIM, as you can see from the conversation https://twitter.com/stevemsft/status/1143977432690466816?s=20 and shown in the below image:

image

This is related to the following notice from the Azure AD PIM Microsoft Graph documentation, stating that Azure AD roles will move to the Azure resource API in the coming months:

image

Update March 19 2020: Tenants are now starting to get migrated to the new Azure AD PIM provider similar to Azure Resources! If you log in to your tenant and see the following info in the Privileged Identity Management blade, then you can also use the new Azure AD provider, as I will show in the examples below:

As the new PowerShell commands are built on Microsoft Graph, this also means that they will work for Azure AD roles depending o the move to the Azure resources API.

Explore Privileged Resources

image

There are two commands for exploring and adding Privileged Azure Resources:

  • Get-AzureADMSPrivilegedResource –ProviderId azureResources
  • Add-AzureADMSPrivilegedResource –ProviderId azureResources

If you want to explore Privileged Azure AD roles you have to change the ProviderId like this:

  • Get-AzureADMSPrivilegedResource -ProviderId aadroles
  • Add-AzureADMSPrivilegedResource –ProviderId aadroles
g-raph

Their equivalent Microsoft Graph API methods for Azure Resources are (Beta endpoint only as per july 2019):

  • List: GET /privilegedAccess/azureResources/resources
  • Get: GET /privilegedAccess/azureResources/resources/{id}
  • Register: POST /privilegedAccess/azureResources/resources/register

Getting or listing Privileged Resources is based on that you have onboarded to Azure AD PIM for Azure Resources, as explained here: https://docs.microsoft.com/en-us/azure/active-directory/privileged-identity-management/pim-resource-roles-discover-resources. You can also add a privileged resource by ExternalId, which I will show an example of later.

The equivalent Graph API methods for Azure AD roles are (Beta endpoint only as per march 2020):

  • List: GET /privilegedAccess/aadRoles/resources
  • Get: GET /privilegedAccess/aadRoles/resources/{tenantid}
  • Register: POST /privilegedAccess/aadRoles/resources/register (Note per march 2020: There are currently no way to programmatically onboard tenants to PIM for Azure AD roles)

Getting or listing Privileged Azure AD roles requires that you have signed up for PIM for Azure AD roles: https://docs.microsoft.com/en-us/azure/active-directory/privileged-identity-management/pim-getting-started#sign-up-pim-for-azure-ad-roles

Examples of Exploring Privileged Azure Resources

To get a list over all privileged Azure resources, just run:

Get-AzureADMSPrivilegedResource –ProviderId AzureResources

This will return a list (capped at max 200 results), with the Id, ExternalId, Type, DisplayName and more for each resource that have been registered to Azure AD PIM:

image

As mentioned above the list is capped at max 200 results, which is a Microsoft Graph limitation for this privileged resource API. You can use the –Top parameter to specify a lower number of returned results, like –Top 50,  but it will just ignore and cap at 200 if you for example type –Top 300.

So to return fewer results we can use the –Filter parameter which support Odata query. I have tried some different combinations, and not all will work as expected. Some examples of working filters:

Get-AzureADMSPrivilegedResource -ProviderId AzureResources -Filter “Type eq ‘resourcegroup'”

Get-AzureADMSPrivilegedResource -ProviderId AzureResources -Filter “Type eq ‘subscription'”

Get-AzureADMSPrivilegedResource -ProviderId AzureResources -Filter “DisplayName eq ‘elvsabootdiag001”

Get-AzureADMSPrivilegedResource -ProviderId AzureResources -Filter “startswith(DisplayName,’rg-‘)”

image

What I found DON’T work is filters for specific resource types like:

Get-AzureADMSPrivilegedResource -ProviderId AzureResources -Filter “Type eq ‘Microsoft.Compute/virtualMachines'”

..or any other specific resource type like Microsoft.Network/loadBalancers, Microsoft.Network/networkSecurityGroups, etc., which I find is a bit strange as I would like to filter on those as well.

If you know the specific resource id you can also get that privileged resource object directly:

Get-AzureADMSPrivilegedResource -ProviderId AzureResources –Id <resource id>

Lets compare this to the Microsoft Graph API methods, using Graph Explorer. To list all managed Azure Resources I run the GET /privilegedAccess/azureResources/resources like this:

image

Which pretty much returns the same list of resources and attributes as I did when running the PowerShell command. There is one important change though, and I mentioned earlier that the PowerShell command would only return max 200 results. In the Graph response I will receive a skip token from where if I run that I will get the next set of potentially 200 more results, and so on.

Graph can also handle filters of course, so lets try that. Here are some variations you can try out:

GET /privilegedAccess/azureResources/resources?$filter=type eq ‘resourcegroup’&$top=5

GET /privilegedAccess/azureResources/resources?$filter=displayName eq ‘rg-auth-dc’

GET /privilegedAccess/azureResources/resources?$filter=startswith(displayName,’rg-‘)

And if you want to get a specific resource with Graph, just specify the id like this:

GET /privilegedAccess/azureResources/resources/ad7327ba-50f4-4f03-a4ee-029f310b6775

Which will return the specific resource in the response:

image

Last, to add a resource as a managed resource to Azure AD PIM, using PowerShell can be done like this:

Add-AzureADMSPrivilegedResource -ProviderId AzureResources -ExternalId “/subscriptions/<your-subscription-id>”

And via Graph:

POST /privilegedAccess/azureResources/resources/register

Request Body:

{
“externalId”: “/subscriptions/<your-subscription-id>”
}

These commands are just to get a list of and adding managed Azure resources for Azure AD PIM, i the next parts we will look into actually managing assignments and settings.

Examples of Exploring Privileged Azure AD role resource

To get a list over all tenants registered for privileged Azure AD roles, just run:

Get-AzureADMSPrivilegedResource –ProviderId aadRoles

This will return a list of directories that have been onboarded for PIM for Azure AD Roles, with the Id referring to tenant id, Type, DisplayName and more:

If you know the specific tenant id you can also get that privileged resource object directly:

Get-AzureADMSPrivilegedResource -ProviderId aadRoles –Id <tenantid>

Lets compare this to the Microsoft Graph API methods, using Graph Explorer. To list all managed Azure AD roles directories I run the GET /privilegedAccess/aadRoles/resources like this:

Note that you also can specify the resource for Azure AD roles directly, by specifying the tenant id like this:

GET /privilegedAccess/aadRoles/resources/{tenant-id}

These commands are just to get a list and settings for tenant onboarded to Azure AD roles management with Azure AD PIM, i the next parts we will look into actually managing assignments and settings.

Explore Role Assignments

image

The following command can be used for listing or getting specific role assignments for Azure resources:

  • Get-AzureADMSPrivilegedRoleAssignment –ProviderId AzureResources –ResourceId <resource id>

And for Azure AD roles, the command would be the following, where the resource id is the tenant/directory id:

  • Get-AzureADMSPrivilegedRoleAssignment –ProviderId aadRoles –ResourceId <tenant id>
g-raph

The equivalent Microsoft Graph API methods for Azure Resources:

  • List: GET /privilegedAccess/azureResources/resources/{resourceId}/roleAssignments
  • List: GET /privilegedAccess/azureResources/roleAssignments?$filter=resourceId+eq+'{resourceId}’
  • List (Mine): GET /privilegedAccess/azureResources/roleAssignments?$filter=subjectId+eq+'{myId}’
  • Get: GET /privilegedAccess/azureResources/resources/{resourceId}/roleAssignments/{id}
  • Get: GET /privilegedAccess/azureResources/roleAssignments/{id}?$filter=resourceId+eq+'{resourceId}’
  • Get (Mine): GET /privilegedAccess/azureResources/roleAssignments/{id}?$filter=subjectId+eq+'{myId}’

And these are the main Graph API methods for Azure AD roles:

  • List: GET /privilegedAccess/aadRoles/resources/{tenantId}/roleAssignments
  • List (Mine): GET /privilegedAccess/aadRoles/resources/{tenantId}/roleAssignments?$filter=subjectId+eq+'{myId}’
  • List (Role): GET privilegedAccess/aadRoles/resources/{tenantId}/roleAssignments?filter=roleDefinitionId eq ‘{myRoleDefinitionId}’

Now that seems a lot of different variations for Graph calls for the one PowerShell command, but as you will see later Graph can be a little more flexible in querying in different ways.

Examples of Exploring Role Assignments for Azure Resources

Lets see some samples for PowerShell first. Now we need to supply a resource id, that can be subscription object, a resource group object, any type of resource objects like virtual machines, virtual networks and so on, and even management group objects. So based on the commands previously shown in the blog post, we should be able to get out the resource id’s first, for example like this:

$myResource = Get-AzureADMSPrivilegedResource -ProviderId AzureResources -Filter "DisplayName eq 'NetworkWatcherRG'"

Get-AzureADMSPrivilegedRoleAssignment –ProviderId AzureResources –ResourceId $myResource.Id

So this returns a list of role assignments for the specified resource, each assignment has its own id, as well as the ResourceId, the RoleDefinitionId (which role that has been assigned, like reader, contributor, owner, etc), SubjectId (which user, service principal, group, etc has been assigned the role). In addition we can get info on any linked eligible assignements, start and end time for assignements, assignment state and if the assignment is active or not, or if the type is inherited or assigned directly to the resource.

image

The same results can be retrieved by first querying for the resource id:

And then querying for the role assignments belonging to this resource:

Basically the above command returns the same as this blade in the Azure Portal:

image

Examples of Exploring Role Assignments for Azure AD roles

If i want to look at Role Assignments for Azure AD roles via PowerShell you would specify ProviderId as aadRoles and the ResourceId to be the tenant id:

$myTenant = Get-TenantDetailsFromGraph
Get-AzureADMSPrivilegedRoleAssignment -ProviderId aadRoles -ResourceId $myTenant.TenantId

This will return all Azure AD role assignments in your tenant:

To return fewer results we can use the –Filter parameter which support Odata query. I have tried some different combinations, here are some examples of working filters:

Get-AzureADMSPrivilegedRoleAssignment -ProviderId aadRoles -ResourceId $myTenant.TenantId -Filter "SubjectId eq '<myId>'"

Get-AzureADMSPrivilegedRoleAssignment -ProviderId aadRoles -ResourceId $myTenant.TenantId -Filter "RoleDefinitionId eq '<myRoleDefinitionId>'"

Get-AzureADMSPrivilegedRoleAssignment -ProviderId aadRoles -ResourceId $myTenant.TenantId -Filter "AssignmentState eq 'Eligible'"

Get-AzureADMSPrivilegedRoleAssignment -ProviderId aadRoles -ResourceId $myTenant.TenantId -Filter "AssignmentState eq 'Active'"

Using Graph API I can explore and list the role assignments using the same filter examples like with PowerShell above:

Now that we have control over role assignments, we can look into the role definitions and settings in the next part.

Explore and Manage Role Definitions and Settings

image.png

The following commands can be used to get and manage role definitions and settings for Azure Resources:

  • Get-AzureADMSPrivilegedRoleDefinition -ProviderId AzureResources -ResourceId <myResourceId>
  • Get-AzureADMSPrivilegedRoleSetting -ProviderId AzureResources -Filter “ResourceId eq ‘<myResourceId> and RoleDefinitionId eq ‘myRoleDefinitionId””
  • Set-AzureADMSPrivilegedRoleSetting -ProviderId AzureResources -Id ‘<myRoleSettingsId>’ -ResourceId ‘<myResourceId>’ -RoleDefinitionId ‘<myRoleDefinitionId>’ -UserMemberSettings -UserEligibleSettings -AdminMemberSettings -AdminEligibleSettings <Microsoft.Open.MSGraph.Model.AzureADMSPrivilegedRuleSetting>

And following commands can be used to get and manage role definitions and settings for Azure AD roles:

  • Get-AzureADMSPrivilegedRoleDefinition -ProviderId aadRoles -ResourceId <TenantId>
  • Get-AzureADMSPrivilegedRoleSetting -ProviderId aadRoles -Filter “ResourceId eq ‘<TenantId>'”
  • Set-AzureADMSPrivilegedRoleSetting -ProviderId aadRoles -Id ‘<myRoleSettingsId>’ -ResourceId ‘<TenantId>’ -RoleDefinitionId ‘<myRoleDefinitionId>’ -UserMemberSettings -UserEligibleSettings -AdminMemberSettings -AdminEligibleSettings <Microsoft.Open.MSGraph.Model.AzureADMSPrivilegedRuleSetting>
g-raph

The equivalent Microsoft Graph API methods for Azure Resources:

  • GET /privilegedAccess/azureResources/resources/{resourceId}/roleDefinitions
  • GET /privilegedAccess/azureResources/roleDefinitions?$filter=resourceId+eq+'{resourceId}’
  • GET /privilegedAccess/azureResources/resources/{resourceId}/roleDefinitions/{id}
  • GET /privilegedAccess/azureResources/roleDefinitions/{id}?$filter=resourceId+eq+'{resourceId}’
  • GET /privilegedAccess/azureResources/resources/<resourceId>/roleSettings
  • GET /privilegedAccess/azureResources/roleSettings?$filter=resourceId+eq+'<resourceId>’
  • GET /privilegedAccess/azureResources/roleSettings/{id}
  • PATCH /privilegedAccess/azureResources/roleSettings/{id}

Explore and Manage Role Assignment Requests

image.png

The following command can be used for exploring and managing role assignment requests:

  • Get-AzureADMSPrivilegedRoleAssignmentRequest. Get role assignment request for a specific resource.
  • Open-AzureADMSPrivilegedRoleAssignmentRequest. Create a role assignment
    request.
  • Set-AzureADMSPrivilegedRoleAssignmentRequest. Update a role assignment
    request.
  • Close-AzureADMSPrivilegedRoleAssignmentRequest. Cancel a
    AzureADMSPrivilegedRoleAssignmentRequest.
g-raph

The equivalent Microsoft Graph API methods:

  • GET /privilegedAccess/azureResources/resources/{resourceId}/roleAssignmentRequests
  • GET /privilegedAccess/azureResources/roleAssignmentRequests?$filter=resourceId+eq+'{resourceId}’
  • GET /privilegedAccess/azureResources/roleAssignmentRequests?$filter=subjectId+eq+'{myId}’
  • GET /privilegedAccess/azureResources/roleAssignmentRequests/{id}
  • POST /privilegedAccess/azureResources/roleAssignmentRequests
  • POST /privilegedAccess/azureResources/roleAssignmentRequests/{id}/updateRequest
  • POST /privilegedAccess/azureResources/roleAssignmentRequests/{id}/cancel

Explore Microsoft Graph as a B2B Guest Account

The Microsoft Graph Explorer (https://aka.ms/ge) is always a great learning source and useful tool for querying the Microsoft Graph, especially as you can use your own Azure AD work account or Microsoft account to query for real data. Another advantage with the Graph Explorer is that you can use it without requiring an App Registration in your tenant, something most users are not able to do themselves as they don’t have the administrator rights for registering apps.

However, sometimes working with Microsoft Graph, I find myself in a scenario where I want to use my own work account, but where the Microsoft Graph resources I want to query is in another Organization’s tenant. These kind of scenarios is usually where my account is invited as a B2B guest user to the resource tenant, and currently there are no way to use the Graph Explorer tool to do that.

So I need another tool, and as an IT pro I could easily write myself some PowerShell code, or as a developer I could create a Web app or Console app querying Graph, and run the queries against the other tenant from there.

On the other hand, I want to do this more inline with the Graph Explorer experience, so the most logical choice for me is to use a tool where I can just run the REST API queries I like. And the most popular tool, both by me and many others are the “Postman” client. You can get it yourself for free at https://www.getpostman.com, both Windows, Linux and Mac downloads are supported!

So in this blog post I will show how I use Postman to query Microsoft Graph in a B2B Guest User scenario.

Requirements & Preparation

So, first you will need to get invited to another tenant where the resources you wan’t to query is. You might already have this Azure AD B2B invitation accepted previously. If you aren’t an administrator in that tenant, you will have to ask someone that has the rights to invite to do that for you.

Next, you will need to get assigned permissions to the resources you want to query in the resource tenant. This is all dependent on what kind of queries you want to run, whether it is for reading, writing or deleting resources for example.

Then, you will need an Global Administrator in that resource tenant to create an App Registration. The following instructions and screenshots can be used as a guide:

First, under the Azure AD experience in the Azure Portal, go to App Registrations and create a new Registration, type a name and a redirect URI like shown below:

image

You can type any name you like, for example in this scenario I want to use it for querying identities. I choose to support accounts in this organizational directory only, as this app registration is for members or guests from this tenant. And since I will be using the Postman i specify the redirect URI of “https://www.getpostman.com/oauth2/callback”. This is important as when I authenticate from Postman later the response will be returned to the Postman client.

When accessing Microsoft Graph you have to authenticate using one of the Oauth2 flows, and the most common is using authorization code flow, (https://developer.microsoft.com/en-us/graph/blogs/30daysmsgraph-day-12-authentication-and-authorization-scenarios/), which is exactly this scenario is all about as I will authenticate on behalf of my guest user account in the resource tenant. That means that I will have to add some delegated Graph permissions to the app registration, and in this example I add User.ReadBasic.All, this will make me able to query users via Graph:

image

After granting Admin consent for the permissions, I can verify that the permissions are added correctly:

image

Next I will need to create a client secret to be used in the request to get an access token, go to certificates & secrets and add a client secret of chosen time expiry:

image

Copy and make sure you save the client secret for later next:

image

Then copy the application id and tenant id and save for later:

image

Click on endpoints (see arrow above), and note the Oauth2 authorization and token endpoints (v2), this endpoints contains the tenantid:

image

With these steps the requirements are complete and we can move on to the postman client.

Authenticating and Querying Graph with Postman

There are a lot of features in the Postman client that you should look into when working with REST API’s. You can organize your queries in Collections, save variables in Environments, synchronize your requests across devices and so on. But for now we will start simple and easy.

In the main canvas at your workspace, create a new query, and for example start with https://graph.microsoft.com/v1.0/me:

image

Don’t push Send just yet, we need to authenticate first. Go to the Authorization section under the request, and select Oauth2, then click Get New Access Token:

image

In the following dialog fill in your details as shown below, where:

  • Token Name: You can type what you want here, this is named reference to the Access Token you will aquire.
  • Grant Type: As earlier mentioned, running graph queries as the logged in user (delegated) use the Authorization Code Oauth2 flow.
  • Callback URL: This is the URL that you specified earlier for Redirect URI under the Azure AD App Registration.
  • Auth URL and Access Token URL: These are the URL’s you saw earlier from the Endpoints setting for the Azure AD App Registration (contains the Tenant ID).
  • Client ID: This is the Application ID for the App Registration.
  • Client Secret: This is the secret key you generated under the App Registration.
  • Scope: Provide a default scope, use the default.
  • State: Scope is used for creating application logic that prevents cross use of Access Tokens. You can type anything you want here.
  • Client Authentication: Select to Send client credentials in body when working with Graph requests.
image

When you click request token, you will be taken to the resource tenant for authenticating with your delegated user. Type in your username and click next. This username can either be a normal user that belongs to this resource tenant, or in this case you can log in with your B2B Guest Account:

image

Now dependent on any Conditional Access policies and settings you might be required to approve sign in:

image

After successfully authenticating I should receive a valid Access Token:

image

If you get an error here, please verify your App Registration settings and that the account you logged in as is correct.

Scroll down and click Use Token:

image

You will see that the Access Token is now filled in the Access Token textbox. Next click Preview Request down to the left, this will add the Access Token to the request as a authorization header:

image

If you click on Headers, you can see the Authorization header has been added with the access token as a Bearer Token value:

image

This Access Token is now valid for 1 hour, and you can run as many requests you like as long as you are inside the delegated permissions (for the App Registration) and the logged in users actual permissions. After 1 hour you can request a new Access Token.

PS! Postman will save the authenticated user session in cookies, if you want to log in as a different user clear those cookies, se “cookies” link right below the Send button.

So, now lets run this query, click Send at verify the response, you should get details for your guest user. From the screenshot below you can clearly see that this user is a Guest account looking at the userPrincipalName attribute:

image

Lets try another query, in this query I list all users that has userPrincipalName that starts with “Jan”, and showing only the displayName and userPrincipalName attributes:

image

As you can see from the result above, I have several guest accounts in this tenant (Microsoft Account, Google, Azure AD) as well as a normal user account. You can also see that the Postman client is helpful in specifying my parameters.

Inspecting a B2B Guest Access Token

If you copy the Access Token you got earlier, and paste it into a site like jwt.ms or jwt.io, we can take a look at the access token contents and claims:

image

If I scroll down a little I see the displayname of the App Registration, but the most important info is the mail claim, which for Guest users will be the external e-mail address. Idp is the source authority for the Guest account, in this case another Azure AD tenant with the Tenant Id as shown below:

image

Working with Environments

Chances are that you might work with several environments in Postman, and that where it’s useful to create environment variables. For example create an environment like shown below:

image

That way you can select which environment you want to work with when running queries, and when referencing variables use “{{ .. }}”. For example under Get New Access Token, change to this:

image

Now, lets finalize this blog post by logging in with another guest account, I will choose my Gmail account, I’ve already set up Google Federation and invited this user to my tenant.

First I need to clear the cookies:

image

Next I will click to Get a New Access Token again, and then authenticate as my Google account, which directs me to the Google login page:

image

After successfully authenticating, and using the new Access Token in the Authorization Header, I can run the basic /me query again, this time showing me that I’m now authenticated to Graph with my Gmail user:

image

And looking inside the Access Token again, I can see that the e-mail address is my gmail and the idp is now google.com:

image

If I had logged on with a Microsoft Account the idp value would have been “live.com”.

Next steps

So, now you know how to authenticate to and query Microsoft Graph with an Azure AD B2B Guest User. I really hope this functionality will come to Graph Explorer eventually, but for now Postman is already an awesome free tool for organizing and running your Microsoft Graph queries that I use a lot myself.

The Microsoft Graph Team has also published this source for a lot of useful collections of Graph queries:

https://github.com/microsoftgraph/microsoftgraph-postman-collections

Get and Set Automatic Replies like OOF with Microsoft Graph

Hi, a short blog post this time as Summer Vacation 2019 is here shortly! And on that note, the topic of the post is to show how you can get and set automatic replies with Microsoft Graph. Automatic replies, previously known as Out of Office (OOF) messages is a mailbox setting for each Exchange Online enabled user.

The Microsoft Graph API documentation for mailbox settings is located here: https://docs.microsoft.com/en-us/graph/api/user-get-mailboxsettings?view=graph-rest-1.0&tabs=http, and besides automatic replies you can also get and set locale (language and country/region), time zone, and working hours.

But for now we will only focus on automatic replies, using the automaticRepliesSetting resource type: https://docs.microsoft.com/en-us/graph/api/resources/automaticrepliessetting?view=graph-rest-1.0.

This resource type has the following settings:

{
   "externalAudience": "String",
   "externalReplyMessage": "string",
   "internalReplyMessage": "string",
   "scheduledEndDateTime": {"@odata.type": "microsoft.graph.dateTimeTimeZone"},
   "scheduledStartDateTime": {"@odata.type": "microsoft.graph.dateTimeTimeZone"},
   "status": "String"
 }

Let’s look at some different samples, and I will use Graph Explorer (https://aka.ms/ge). Please note that every end user already have user permission to get or set their own mailbox settings, but you need an Exchange Admin role to get or set the settings for other users in your organization. In addition, if you create your own app registration for Microsoft Graph, you need to make sure the app has either MailboxSettings.Read or MailboxSettings.ReadWrite permission.

In Graph Explorer, after you sign in with your work account, you can modify these permissions if needed:

image

After signing out and in again you will be prompted to consent, if you havent already:

image

Get Current Mailbox Settings

To get your own current settings you can run the following:

GET /me/mailboxSettings

In Graph Explorer this would look like this, and you might have some previous values set here. In my example automatic replies have a status of disabled:

image

To get another users mailbox settings you can run the following (but then you must be an Exchange Admin):

GET /users/{id|userPrincipalName}/mailboxSettings

Simple Update of Status

Lets see how Microsoft Graph can be used to change the status value, there are 3 different settings:

  • disabled. No automatic replies are sent.
  • alwaysEnabled. Automatic replies are sent as specified.
  • scheduled. Automatic replies are sent if between a specific time period.

First, change the method i Graph Explorer to PATCH:

image

Then you need to supply a request body. This sample is just for enabling automatic replies:

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#Me/mailboxSettings",
    "automaticRepliesSetting": {
        "status": "alwaysEnabled",
    }
}

So paste that body to Graph Explorer and then Run Query:

image

You should then get a successful response. Likewise you can set the status to “disabled” again, or to “scheduled”. But using scheduled means that you must set some datetime values as well.

Set Scheduled Automatic Replies

To set scheduled automatic replies, in your request body include the resource types scheduledStartDateTime and scheduledEndDateTime. You can read more about that resource type here, including available time zones: https://docs.microsoft.com/en-us/graph/api/resources/datetimetimezone?view=graph-rest-1.0. This is a sample specifying a scheduled automatic replies:

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#Me/mailboxSettings",
    "automaticRepliesSetting": {
        "status": "scheduled",
        "scheduledStartDateTime": {
            "dateTime": "2019-07-15T08:00:00.0000000",
            "timeZone": "Europe/Berlin"
        },
        "scheduledEndDateTime": {
            "dateTime": "2019-08-09T16:00:00.0000000",
            "timeZone": "Europe/Berlin"
        }
    }
}

Customize internal and external reply messages

The last part is where we put it all together, specifying the following values:

  • internalReplyMessage: Plain text or HTML formatted message sent to all internal users in your organization as the automatic reply.
  • externalReplyMessage: Plain text or HTML formatted message sent to all external users as the automatic reply, but depending on this value:
  • externalAudience: If “none”, no external users will get automatic replies, if “contactsOnly” replies will only be sent to users in your contacts, and if “all” every external user will get a reply.

So this is a working sample of a complete request body:

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#Me/mailboxSettings",
"automaticRepliesSetting": {
        "status": "scheduled",
        "externalAudience": "contactsOnly",
        "internalReplyMessage": "<html>\n<body>\n<div></div>\n<div>Hi, I'm enjoying summer vacation 2019. I'm back at work August 12th!</div>\n<div><br>\n</div>\n<div>Kindly Regards</div>\n<div>Jan Vidar Elven</div>\n<div></div>\n</body>\n</html>\n",
        "externalReplyMessage": "<html>\n<body>\n<div></div>\n<div>Hi, I'm enjoying summer vacation 2019. I'm back at work August 12th!</div>\n<div><br>\n</div>\n<div>I'll only read e-mails intermittently, and rarely respond before I'm back. Please contact management if anything urgent business needs follow up. Contact info on our website.</div>\n<br>\n</div>\n<div>Kindly Regards</div>\n<div>Jan Vidar Elven</div>\n</div>\n<div></div>\n</body>\n</html>\n",
        "scheduledStartDateTime": {
            "dateTime": "2019-07-15T08:00:00.0000000",
            "timeZone": "Europe/Berlin"
        },
        "scheduledEndDateTime": {
            "dateTime": "2019-08-09T16:00:00.0000000",
            "timeZone": "Europe/Berlin"
        }
    }
}

In Graph Explorer:

image

And I can verify in my Outlook settings:

image

Summary and Usage Scenarios

Beside that it is always fun to learn something new about the Microsoft Graph, and automation, the reality is that for many users they will just click to enable or disable automatic replies directly in their Outlook client, both Office Outlook, Outlook Mobile and Outlook on the Web supoorts this. Finding out how to do it with Graph took me just under 2 hours, including writing this blog post. But then again, I learned something new! And I picked up a couple of more tips and tricks on different JSON Request Body constructs 😉

Anyway, in a bigger picture, Graph API is great for customizing, integrating, reporting and automating, so if your organization maybe have create a vacation calendar, you could use the Graph API to automatically enable or disable out of office replies, this is just one example, many more will exist. Please share with me in the comments if you have done or plan to do something with this or similar.

Smile

But first: Summer Vacation 2019! And I’m all set with automatic replies !

Speaking at Microsoft Ignite – The Tour Stockholm

It is with great pride I can announce that I will speak at Microsoft Ignite – The Tour, in Stockholm April 24-25 2019. This conference, which already is sold out and now only available on waiting list, will be held at Stockholmsmassan, and you can read more about it here: https://www.microsoft.com/sv-se/ignite-the-tour/Stockholm.

Ignite The Tour Stockholm will have over 150 different breakout sessions, theatre sessions, modules and workshops, covering 10 learning paths. Speakers will be from Microsoft, and from the MVP and Regional Director community, which I’m so fortunate and honored to be part of 😉

I will be speaking at the following sessions:

In addition to this I will participate on the following hands-on workshop as a proctor:

You will also find me at the experts area and doing booth duty, I will be at the following demo stations at the Hub and Microsoft Showcase area, covering topics on Azure and Azure AD:

  • Demo Station #5 (Azure): Day 1 1600-1800: “Getting Started with Azure Log Analytics and Azure Monitor using Azure AD Activity Logs
  • Demo Station #6 (Azure): Day 2 0800-1200: “Getting Started with Azure Log Analytics and Azure Monitor using Azure AD Activity Logs

I’m really excited for presenting these sessions and being part of the Ignite The Tour Community! Hope to see you there 🙂

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

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

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

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

Export the PowerApps Package

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

image

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

image

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

image

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

image

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

I can then download the package:

SNAGHTML9abd28

The package is downloaded as a zip file:

image

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

image

Export the Custom Connector swagger file

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

image

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

SNAGHTMLb16f76

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

image

Community Download

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

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

Import the Custom Connector swagger file

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

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

    image

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

    image

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

PS! Prerequisite

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

Take a note of the application ID and secret key:

image

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

image

Import from OpenAPI URL

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

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

    image

    Verify the URL and click Continue.

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

    image

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

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

    image

    Click to go to the next Definition page.

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

    image

    Click “Create connector”.

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

    image

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

    image

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

    image

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

    image

After testing this the custom connector is ready to use.

Update from OpenAPI URL

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

  1. Provide the URL for the swagger json file:

    image

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

    image

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

    image

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

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

    image

    Click Update Connector to save the changes.

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

    image

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

Import the PowerApps and Flows Package

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

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

image

Then browse to the zip packaged to start uploading:

image

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

image

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

image

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

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

image

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

image

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

image

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

For example something like this from my company:

image

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

Thanks for reading, hope it has been helpful!

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

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

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

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

Microsoft Graph API for Azure AD PIM

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

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

image

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

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

SNAGHTML1778e65

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

image

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

image

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

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

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

image

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

image

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

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

image

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

image

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

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

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

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

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

image

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

image

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

image

And after that I can activate the role:

image

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

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

image

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

Add Microsoft Graph Permissions to App Registration

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

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

image

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

image

image

image

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

image

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

image

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

Adding PIM API’s to Custom Connector Operations

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

image

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

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

image

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

image

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

image

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

image

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

The response now looks like this:

image

We can also validate that the response looks ok:

image

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

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

image

Request and Import from sample:

image

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

image

Default Response and Import from sample:

image

Check validation and the Update Connector:

image

Next I want to create another action for

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

image

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

image

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

image

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

image

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

image

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

image

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

image

The request will look like this now:

image

Default Response and Import from sample:

image

And we can validate the response:

image

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

image

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

image

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

image

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

image

The test should complete successfully and return my role assignments:

image

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

image

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

image

image

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

image

Starting with the PowerApp

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

Start by Create an app:

image

Then select a blank canvas, and phone layout:

image

You should now have an empty app like this:

image

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

image

A quick summary of the above:

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

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

image

And then save the App:

image

Creating the Flow for Getting My Role Assignments

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

image

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

image

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

image

Type the name MyRolesArray and select Type Array:

image

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

image

Our Flow should look like this now:

image

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

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

image

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

image

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

image

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

image

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

image

I also rename the step before I proceed:

image

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

image

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

image

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

image

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

image

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

image

This is the JSON schema I used:

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

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

image

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

image

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

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

image

Creating the Flows for Self Activate and Deactivate Roles

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

image

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

image

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

image

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

image

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

image

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

image

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

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

image

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

image

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

image

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

image

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

image

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

Connecting the PowerApp to the Flows

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

image

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

image

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

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

Like this:

image

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

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

image

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

image

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

image

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

Set(SelectedRole,First(lstMyRoles.SelectedItems))

It should look like this:

image

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

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

image

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

image

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

image

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

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

AzureADPIMApp1

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

image

This Flow needs two inputs:

image

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

image

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

image

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

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

Like this:

image

And similarly for the DisplayMode property for the Deactivate button:

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

image

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

image

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

image

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

image

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

image

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

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

And for the Deactivate button I change the OnSelect to:

image

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

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

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

image

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

image

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

Publish and Run the Azure AD PIM App

On the File menu click Save, and the Publish:

image

You can also Share the PowerApp in your organization:

image

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

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

image

After that you should be able to refresh your roles:

image

Let’s try to activate a role:

image

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

image

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

image

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

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

image

Known issues and tips

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

image

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

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

image

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

Access Microsoft Graph API using Custom Connector in PowerApps and Flows

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

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

image

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

App Registration

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

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

image

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

image

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

image

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

image

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

image

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

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

image

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

image

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

image

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

image

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

Create a Custom Connector in PowerApps

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

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

image

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

image

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

image

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

image

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

image

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

image

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

image

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

image

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

image

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

image

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

Prepare queries in Graph Explorer

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

http://aka.ms/ge

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

image

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

image

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

I will get this response for my user:

image

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

image

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

image

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

Create Custom Connector Operations

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

image

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

image

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

image

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

image

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

image

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

The response now looks like this:

image

We can also validate that the response looks ok:

image

Click on Update connector to save this operation.

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

image

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

image

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

Testing the custom connector

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

image

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

image

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

image

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

image

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

image

Now, let’s test the second action:

image

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

image

The response is also successful.

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

Set up the PowerApp and use the Connector

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

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

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

image

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

image

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

image

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

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

image

First a little explanation of this action:

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

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

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

image

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

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

image

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

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

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

Running the PowerApp

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

image

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

image

Lets update some text in the About me textbox:

image

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

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

image

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

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

image

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

Using Microsoft Flow

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

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

image

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

image

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

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

image

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

image

Then find the Flow I created and add that:

image

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

image

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

image

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

image

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

image

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

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

Sharing the PowerApp with other users

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

image

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

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

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

image

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

image

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

image

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

image

And after consenting click to Allow:

image

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

image

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

image

Summary

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

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

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