
What’s up people! I am back with another awesome blog post. This time I will delve into using Microsoft Power Automate (formally known as Microsoft Flow) to automate tasks against Azure AD and on-prem Active Directory (AD DS). Yes, you can technically accomplish this! What is awesome about Microsoft Flow is you can orchestrate tasks against different systems without having to write code or with writing some code (like maybe some PowerShell).

This will be a lot of content to cover so I am splitting this into two posts. The first post will be focused on using Microsoft Power Automate for Azure AD Tasks (connecting to the Microsoft Graph). The second one will be focused on using Microsoft Power Automate to connect to AD DS.

Article List

Setting the Stage

Think about what the goal is for the Flow to accomplish. Here are some other items to think about:

How will the Flow be triggered?

The tasks the flow should execute

What services should the Flow integrate with?

What connectors exist for Flow?

One interesting thought is that even if a built-in connector does not exist for a service, most likely you can integrate with anything that has a REST API or a way to trigger a web hook.

There is a pretty extensive list of triggers to kick off a flow!

For this Azure AD example (part one), we will use the HTTP Connector, the ‘Reoccurrence trigger’ and some native Flow actions like setting variables, parsing JSON and creating tables. I will be creating a flow which checks for Risky Users via the Graph and disables the user objects in Azure AD. Keep in mind that you don’t have to make the action to delete users, you could perform any action which is supported by the Graph. In this case we will be modifying users but we could change this to any other type of object available in the Graph.

Defining Azure AD Requirements

Here are some things to start thinking about when setting up Power Automate for Azure AD Tasks:

Service Principal secret type (shared key or certificate?)

Microsoft Graph permissions (ensuring the principal of least privilege is used)

The type of objects being read or modified

The actions being performed against the objects

Specific queries to use to obtain lists of objects

Get ready to rock!

Using Power Automate for Azure AD Tasks

My flow was basically a proof-of-concept. For part one of this blog series, I will show you how the actual flow looks in the visual editor for the Azure AD part:

Inside the ‘Remediate Users Loop’ is where the magic happens, but before we get there, I will give an overview of what the logic in the flow before the loop.

Flow Prerequisites

In this section I will provide the steps required to build the necessary arrays and to query the MS Graph for the users we want to update. This will also cover parsing the JSON data returned from the Graph and will cover how to set up the HTTP Connector to connect to the Graph.

Define the Trigger In this case, we are using the schedule based trigger

There are many other triggers as well such as: when a file is created in SharePoint, when a new form is completed in Microsoft Forms, when an event occurs in Azure Monitor, etc.) Initializing variables In Power Automate you need to initialize variables before they are used within the Flow

To do this, add some ‘Initialize variable’ actions to the flow

Variables can be one of the types shown in the image below:

When initializing a variable it can be one of the types shown above

In this example, I am setting the following variables:

RiskyUserArray Array UserObjectId String ImmutableId String

Use the HTTP Connector to call the MS Graph We are going to send a GET request to https://graph.microsoft.com/beta/riskyusers

The HTTP Connector allows for the client ID and secret to be entered within the advanced settings

You will need the client ID, secret and the tenant ID for your Azure AD tenant

Since this is running in the Service Principal (also known as SP) context (no signed-in user context exists) the SP will need the “IdentityRiskyUser.Read.All” application-level permission for the MS Graph Advertisement

Here is what the configuration should look like:

Add an action to parse the JSON message returned from the Graph Add a ‘Parse JSON’ action to the Flow Ensure the ‘Body’ from the previous action is added to the Content field as pictured below (the dynamic content dialog box is amazing for working with data in the Flow pipeline!)

You can use the ‘Dynamic content’ to pull out data from the pipeline to pass to the next action in the Flow!

Add the following schema to the Parse JSON action (or you could can call the Graph with Graph Explorer, Postmon, PowerShell or your scripting language of choice to generate your own schema if this does not work for you):

{ "type": "object", "properties": { "@@odata.context": { "type": "string" }, "value": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string" }, "isDeleted": {}, "isGuest": {}, "isProcessing": { "type": "boolean" }, "riskLevel": { "type": "string" }, "riskState": { "type": "string" }, "riskDetail": { "type": "string" }, "riskLastUpdatedDateTime": { "type": "string" }, "userDisplayName": {}, "userPrincipalName": {} }, "required": [ "id", "isDeleted", "isGuest", "isProcessing", "riskLevel", "riskState", "riskDetail", "riskLastUpdatedDateTime", "userDisplayName", "userPrincipalName" ] } } } }

Add an ‘Apply to each’ action and loop through the array of objects from the parsed JSON data Make sure that the ‘value’ item is selected from the previous Parse JSON action

Add an action of ‘Append to array’ inside the loop and add ‘Current item’ as the value (the current item being processed within the loop) Thanks to some feedback from a Reddit user, I have updated step six here. Adding a loop to set the RiskyUserArray works but it is not required. Instead we can just set the RiskyUserArray variable by adding the response from the parse JSON action as the value. Add a ‘Set variable/ action and set the value to be ‘value’ from the previous action Be sure to select the value item under the Parse JSON action in the dynamic content window If you followed along and have everything set up correctly, you can actually perform a test run and confirm you have an array of users (assuming you have risky users in your tenant): The output from the flow test allows you to view the actual responses and data in the pipeline of the flow!

Updating Azure AD User Objects

In the previous section, we obtained a list of users that we want to make changes to and placed those users in an array. Now we will loop through the array of users to apply changes to them via the Graph. These PATCH requests to the Graph will update the user objects in the Azure AD directory store. This essentially enables Power Automate for Azure Active Directory task automation.

Add the “User.ReadWrite.All” application-level permission to the SP used previously This will ensure the SP can update user properties against the Azure AD tenant

Changes made by the SP will be recorded in the Azure AD Audit logs

The Azure AD Audit logs will have events for changes made by the SP

It is worth noting that Sign-in logs are not yet available for SPs. However, this feature is planned for a future release and is currently in private preview.

Add a new ‘Apply to each’ action to process the users in the RiskyUsersArray (ensure this array is selected in the output field) Add a ‘Set variable’ action to set the ‘UserObjectId’ variable

Make sure to use the ‘Expression’ tab to add the value of item()?[‘id’] so the Azure AD objectId is added as the value of the variable for each user

Add the expression above and click the ‘OK’ button

Please note that steps four through six are required for the AD DS tasks we will perform in Part Two of this blog series. You can skip them for now if you would like.

Add another HTTP Connector to query the MS Graph for the ImmutableId property using the UserObjectId variable we just defined The Dynamic content feature makes it really easy to stick the variable into the request!

Make sure the ‘?’ is at the end of the request URL

Use the same advanced options as before for the previous Graph calls

Make sure to set the select parameter in the request so the response only has the onPremisesImmutableId property

Add another ‘Parse JSON’ action to parse the response from the Graph Ensure to select the ‘Body’ from the response from the Graph as the content

Use the following schema or create your own as mentioned previously:

{ "type": "object", "properties": { "@@odata.context": { "type": "string" }, "onPremisesImmutableId": { "type": "string" } } }

Add a ‘Set variable’ action to set the ImmutableId variable

Ensure the output from the ‘Parse JSON’ action is used as the value:

Use the Dynamic content fields to select the parsed JSON response from the Graph as the value of the variable

Create one final HTTP Connector action. This is the action which will update the users in Azure AD! We will be using the UserObjectId variable set previously

Set the same advanced options used on the other HTTP Connectors for the previous Graph calls

Ensure the PATCH method is used on the request

Set the following values in the ‘Body’ of the request:

{ "accountEnabled": false }

The action should look like this when configured properly:

The HTTP connector action for disabling users in the Graph

Test the flow using the test button on the top right of the Power Automate portal:

Power Automate lets you test flows and view the results/output of each step within the flow

Validate the changes made in Azure AD by using one of the following methods: Check the MS Graph users API to confirm the accountEnabled property is set to ‘false’

Use the Azure AD v1 or v2 PS modules to check if the account has been disabled

Check the Azure AD Admin Center to see if the ‘Block sign in’ option is set to ‘Yes’.

Check the Azure AD Audit logs to see if events appear in the Audit log indicating the SP updated the expected user objects

Conclusion

If you made it this far, you have seen how you can use Power Automate to automate changes against Azure AD. In the above scenario we disabled users directly in Azure AD who were marked as risky in Azure AD Identity Protection. You can easily use these tools and modify the actions taken above to meet your specific requirements. If the MS Graph supports the changes you need to make it is possible!

I realize that the example above is great, however, disabling synced users directly in Azure AD presents issues. The next time Azure AD Connect exports to Azure AD, these users would be marked as enabled again as on-prem AD is the source of authority (SOA) for the ‘accountEnabled’ (UserAccountControl) property.

Keep in mind that we have a Part Two of this blog series coming up. In it, I will demonstrate how to use Power Automate to connect to AD DS (on-prem Active Directory) to disable users via PowerShell. This will all run from one flow so moments after the accounts are disabled in Azure AD, they will also be disabled in on-prem AD which prevents the SOA issue.

I hope you enjoyed this blog post. Please leave comments and feedback below and subscribe to our mailing list. Until next time, rock on!