I have recently been chatting with a friend who had a requirement to check if a particular user had a group membership with Azure AD to support a Governance function. This could be something as simple as "I have an Azure AD Security Group which contains all managers" and I only want to perform an option if the user is a manager. I thought this was a great opportunity to showcase two ways of interacting with Azure AD by using Flow, so I demonstrated the two techniques, and now I'm going to share it. I'll point out now, for the eagle eyed readers, I won't be renaming my actions as I want it to be clear which action I'm using at what point in the screenshots :)
Credit goes to Keith Whatling, who's a PowerApps guru and #PowerAddict who asked me the question and got me looking at the problem.
I approached the solution in two different ways:
- Azure AD Actions
- Accessing Microsoft Graph
Using Azure AD
There are a good set of actions which have been published by Microsoft which allow you to interact with Azure AD in a number of different ways.
There are some really cool actions here, however at the time of writing this blog there are only actions available, there are no triggers. Full documentation for this connector can be found here:
The documentation will go through what is required for each action, but also what the required permissions are for the connection account in Azure AD. Obviously always try to adhere to the principle of least privilege, so if you don't need to write back to Azure AD, then use the Group.Read, User.Read, Directory.Read permissions rather than the ReadWrite permissions.
In the following example, I'm going to get the group membership for the user who has triggered the Flow, and that can be used later to apply further logic.
For the purpose of this demo I have manually triggered my Flow, but that could obviously be whatever you needed it to be. The first action I'm going to perform is to get the profile for the user who is running the Flow by calling Get my profile (V2) from the O365 Users connector.
The key piece of information which I need from "Get my profile" is the User Principal Name (UPN) of the user which will allow me to find specific information in Azure AD. From there I'm going to use the "Get groups of a user" action which will take an input of the UPN from the previous action. The other required option if whether this is Security Enabled Group only, so this determines if we're going to pull back just Azure AD Groups (Yes) or if we're also going to pull back O365 Groups (No).
For the purpose of this, I'm going to initialise myself an Array to store the detail of the groups being returned, however the results I've got back from the previous step is just a bunch of GUIDs which won't really help me to keep things nice and clean.
I'm going to take the output from the "Get groups of a user" action and loop through each GUID, push that to the "Get group" action and get back something which is more useful. On each iteration, i.e. for each Group, I'm going to push the Display Name into my array.
I now have a list of groups which my user belongs to, so I could then start to apply conditional logic to determine any follow on actions.
Using the Microsoft Graph
I then performed the same process again but using the Microsoft Graph to achieve the same goal. The whole process starts in exactly the same way, however the difference now is that I'm going to use the HTTP action to call out and get the information back.
The first two parts of my demo flow are exactly the same, I'm still going to have a manual trigger, and I'm going to get the profile of the person running the flow by using Get my profile (V2). The difference is that I'm now to going to call the Graph API to get the same information.
One of the great improvements that has been made to the HTTP action is that you can now bake in all of your authentication info so that you don't have to make multiple calls. Make sure you click on "Show advanced options" otherwise you could miss this.
Before completing the following details you'll need to register a new App within Azure AD which you can use to authenticate through OAuth. One of the better blogs I've found to follow here is:
Complete each of the aspects in the form:
- Method: Post
- Uri: https://graph.microsoft.com/v1.0/directoryOutput/<Object ID of the user>/getMemberGroups
- Body: the JSON version of "securityEnabledOnly" switch
- Authentication: Active Directory OAuth
- Authority: The login url for Microsoft: https://login.microsoft.com
- Tenant: this is the name of your tenant. I've seen other blogs which have used the TenantID here, but I'll admit I couldn't get it working like this. The only way I could get it working was to put the Tenant name in e.g. contoso.onmicrosoft.com
- Audience: What is the URL I'm going to hit? i.e. https://graph.microsoft.com
- Client ID: the Client ID which was generated by my App Registration in Azure
- Credential Type: Secret
- Secret: The secret which was generated from your App Registration
The results which I get back from this aren't as pretty as using the Azure AD actions, as the return will come back with JSON. I'll need to parse this JSON to make it workable, and this is quite easy. If I put the Flow into a test, I can grab the JSON body which is returned, and then use that to generate my JSON schema.
I will use the Data Action: Parse JSON to take the Body returned from HTTP call. Before I do that, I'll use the JSON which was generated in my test, press the "Use sample payload to generate schema" to generate the Schema for me, which then makes the output useful going forward.
I can then complete the Flow in exactly the same way as I did before by looping through the Array and getting the group back.
So now we've looked at two ways in which we can get group membership information using Flow. It's useful to at least have a go at the direct HTTP call method just so that you can understand what is actually going on when you're using the built in actions.
The biggest takeaway for me while I was looking at this issue was baking in all of the authentication into single HTTP call, reducing multiple calls into one.
I hope this was useful, if you have any questions please don't hesitate to shout!