Skip to main content

Using Custom Connectors and Microsoft Graph API's to Manage Licenses in Power Automate - Part One

Happy June folks! I come to you with another post, but this time I wanted to change it up and show you something else I have just finished working on. As a SysAdmin, one of the most common issues we run into is managing licenses. Working at a post-secondary institution makes this an even greater challenge, as you have both students, staff and faculty constantly coming as well as going. Managing to keep up with this constant change can introduce great administrative overhead which takes away time from important upkeep of other systems and initiatives. You may also notice this same issue in large corporations or in other government organizations. To help combat this, I wanted to create a flow that can do the following:

  • Get the user and their licenses
  • Determine their last sign-in and the date
  • Conditional to determine if the user is past the "cutoff" date
  • Remove the user from a group where the license is assigned
The only problem with doing this is that Power Automate does not have the capability (as of writing) to get the user's last sign-in with a pre-made connector. To get around this, I had to create my own custom connector using Microsoft Graph to gather the user's last sign-in details. Here is the details of the custom connector:

General Information

  • Scheme: HTTPS
  • Host: graph.microsoft.com
  • Base URL: /v1.0

Security

This part is a bit tricky. To proceed with this, you must make an enterprise application and app registration. Additionally, the enterprise app must have the following API permissions to work:
  • AuditLog.Read.All
  • Directory.Read.All
  • User.ReadWrite.All
Now I know what you're thinking- why are you not using least privilege? In this case, I tried to but I found that there were difficulties in doing so as this flow is required to read a group and get information from the directory. In all cases, practice least privilege when you can and ensure that only the people who require these roles get access. You can also use Privileged Identity Management and govern the roles that have these attributes or the attributes themselves.


Once you have that squared away, it is just a matter of then creating a new secret and then applying it to the connector with the following parameters:
  • Authentication Type: OAuth 2.0
  • Identity Provider: Azure Active Directory
  • Client ID: add your Client ID
  • Client secret: add your secret that you generated from the app registration
  • Authorization URL: https://login.microsoftonline.com
  • Tenant ID: add your tenant ID. This can be found in the Azure Portal under "Tenant Properties"
  • Resource URL: https://graph.microsoft.com
  • Enable on-behalf-of login: false
  • Scope: Directory.Read.All User.ReadWrite.All AuditLog.Read.All
  • Redirect URL: this will be generated when you save the custom connector.

Creating the Definitions

This is the part that will actually call on the Microsoft Graph API to carry out the functions we need. With this in mind I should note that the Operation ID could be unique to your tenant, in which you may be required to find your own. For this, visit Microsoft Graph Explorer and use the following GET request:

https://graph.microsoft.com/v1.0/users/{userId}/licenseDetails

This in turn will give you the following result:

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users()/licenseDetails",
    "@microsoft.graph.tips": "Use $select to choose only the properties your app needs, as this can lead to performance improvements. For example: GET users('<guid>')/licenseDetails?$select=servicePlans,skuId",
    "value": [
        {
            "id": "gHe4LsjI706Gy7mIO8jPohyUoe1PPJVJtevoWkIXWrk",
            "skuId": "eda1941c-3c4f-4995-b5eb-e85a42175ab9",
            "skuPartNumber": "POWERAUTOMATE_ATTENDED_RPA",
            "servicePlans": [
                {
                    "servicePlanId": "375cd0ad-c407-49fd-866a-0bff4f8a9a4d",
                    "servicePlanName": "POWER_AUTOMATE_ATTENDED_RPA",
                    "provisioningStatus": "Success",
                    "appliesTo": "User"
                }..............

The ID that is highlighted is the operation ID that is required to complete this action. Take note of it, and then create a new action with the following information:

  • Summary: License PA Connector - Get Licenses
  • Description: This request retrieves all licenses for the user account.
  • Operation ID: Insert the Operation ID provided
  • Visibility: none
Now that we have the general information down, we now have to create a GET request. Using the GET request we made to Graph Explorer, add a GET request with that link. It should automatically populate the path and query accordingly. 

Additionally, we will need to create another definition and API request for gathering the sign-ins of the user. To do this, we will send another GET request to Graph Explorer:

https://graph.microsoft.com/v1.0/users/{userId}

This should result in us being able to get the other operation ID which we can then insert into our second action with the following parameters:

  • Summary: License PA Connector - Get Last Sign In
  • Description: This request retrieves user's last sign-in
  • Operation ID: Insert the Operation ID provided

The path and $select should also populate automatically. If not, then ensure that the path and query fields contain the following:

  • Path: userId
  • Query: $select (this will be useful later)

Tying it all together

We can now begin saving and testing our connector. To do so, go to the "Test" section and attempt to connect. If all is well, you should be prompted to sign-in and the connector should work correctly. We must then take the redirect URL that is generated and add it to our app registration. This can be found at the bottom of the "Security" tab. When this is all said and done, we can now begin working on our Power Automate flow.

What's Next?

Given that this post is already getting pretty long, I am going to end it here for now. I hope that this article has helped you on the right track to be able to implement this in your own environment. It is a bit of a setup, but as you work with it, everything should tie together and you'll have the first leg of the process done. Should you have any questions, feel free to put them in the comments or contact me directly. I also hope to make a full YouTube video on this as well in case you don't want to read this whole post. Until next time!

test

Using Power Automate to Update Contact Information

 We've all been there- you have a large organization who has out-of-date contact information. What do you do? You could go around to each department and ask them nicely to update their information, or send out an org-wide email prompting people to do so. However, this is tedious and oftentimes a pointless task. By the time you update one department, you're running to fix another. What if you could put the power back in the department's hands to do so? This is a struggle I faced recently as I was trying to find was I could conjure up some updated contact information for each department. As I did my research, I found that I was not alone in this endeavour as it seems that many IT professionals would love to make this process a little bit less painful. With this in mind, I introduce to you my latest flow! This flow will allow you to encourage users to update their contact information, without the overhead that comes with manual effort. In addition to this, this flow utilizes t...

Using Custom Connectors and Microsoft Graph API's to Manage Licenses in Power Automate - Part Two

Hello again! Didn't I promise you that I'd be back to wrap this up? Well, here I am to give you the second tidbit of information that you need to get this started. If you haven't already, take a look at my previous post where I go into depth about creating a custom connector in Power Automate to retrieve the latest sign-in and also gather the user's licenses. Now that we have the custom connector ready, we can now get into the meat n' potatoes of this series. In this post, I will show you the flow that makes this possible and how you can use the custom connector you have created to tie it all together! Hope you enjoy. Understanding the Logic Before we can begin creating the flow, we should first understand how the flow will work. I designed this to flow to be triggered manually, but you may want to schedule it or use another trigger. The trigger will depend on your organization's policies, so please adjust accordingly. Once triggered, the flow will use the Entra...