In one of the latest blog posts, I shared how we can create a red button automation solution to take action when a user account is compromised. Today we’re going to build our own user onboarding automation with the low-code solution Azure Logic Apps.
This is the first part of a user onboarding automation series that I will share (2nd part is found here). In the first part, we focus on automatically creating a user account in Entra ID (formerly Azure AD), including assignment of Microsoft licenses, (department) group membership, and informing relevant people, like HR, IT, and the manager.
In one of the following blog posts, we expand the flow to also be able to create a user account in the on-premises Active Directory, and I will also share some automation related to Temporary Access Passes and Windows 365. But that’s planned for later 🙂
Of course, several HR solutions on the market can initiate the creation of user accounts in Entra ID or the on-premises active directory. Or we can automate some tasks with for example Entra Governance. But not every company can effort buying such an application or license. Therefore I’m sharing a low-cost solution like this, which is easy to set up. Also, this low code solution could be integrated with several HR systems, as Logic Apps contains a lot of third-party integration or can be triggered via webhooks.
The Logic Apps flow is available on my GitHub repo for easy deployment.
The solution in short
The whole solution relies on Azure Logic Apps, a cloud-based platform that allows you to create and run automated workflows with little to no code. The workflow can make Microsoft Graph API calls to perform all kinds of actions, like creating a user account.
The automation solution is triggered by creating a new item in a SharePoint List. To make it look a bit nicer for your HR department, we can create a form with Microsoft Forms to create those items. When the form is filled in with the required information, the flow starts to run and creates the user account in Entra ID. At that moment the flow also assigns the manager and if a laptop needs to be prepared the IT Service Point is informed via e-mail to prepare a device.
Next, it adds the user account to the needed groups for Microsoft license assignment and does the same for department-related Entra groups.
As last HR will be informed the account is created and the manager will be informed about the account creation and hire date.
In this example flow the user account is disabled out of security concerns. On the day the user starts at the company, the user account is enabled and a Temporary Access Pass is sent to the manager. But that is handled in a separate flow and shared in an upcoming blog post to not make the post too hard to follow.
Requirements
We have some requirements that need to be in place before we can use our Logic Apps flow.
We need to have two SharePoint Lists. Depending on the number of departments and licenses, you might want to use just one or even three SP Lists, but more on that later.
We need to have a (service) account with access to these SP Lists.
And we need to have a (service) account with the permission to send e-mail from a shared mailbox.
To take several actions via Graph API calls, we make use of a Managed Identity (MI):
A Managed Identity in Azure is a feature that provides an automatically managed identity in Entra ID for applications to use when connecting to resources that support Azure AD authentication.
We have the option to use a system-assigned and user-assigned managed identity, as you can read in the documentation. In my case, I make use of a system-assigned MI, as that is considered the most secure.
This Managed Identity needs to have (application) permission to execute all the Graph calls we make. These are the application permissions needed for our flow;
User.ReadWrite.All
GroupMember.ReadWrite.All
Setting up the SharePoint Lists
For this automation implementation, we need at least one SharePoint List with a form which can be used by HR to fill in the new colleague’s information and that starts the automation flow.
In the form, several choices need to be made depending on what is applicable for the new user, like which licenses the user gets assigned and to which department group the user needs to be added. In this post I show two ways of assigning those. For licenses, I used a column of type choice and filled in the available licenses. In the flow, I handle this with a switch and several cases.
For department, I use an additional SharePoint List in which I store all the departments and the relevant Entra groups. In the flow, this is handled by retrieving the items of this department list and one HTTP Action.
Two different approaches which I’d like to show, so you can make a choice yourself about what suits your needs.
The SharePoint List for the User Onboarding contains the following columns:
Full Name
First name
Last name
Private mail
Job title
Manager (type people)
Department (lookup)
Country (Choice)
Hire date (date and time)
Microsoft licenses (Choice. Multiple allowed)
Laptop (Choice)
The first columns are of type Text (single line of text).
The manager is of type people so it makes it easily to search through the Entra directory and select the correct manager.
For country and license, I choose to use type choice and fill in the available values.
For country, I use the country codes (NL, BE, AU etc), which can be directly used as usage location in the flow. For license I have these choices; Microsoft 365 Business Premium, Windows 365 Frontline, Windows 365 Enterprise, and Microsoft Viso P1. Just some examples to show how this does work in the flow. And for license, I set the option multiple allowed.
For the hire date, I use type date and time.
As I already make use of an additional SP List to store the different departments, we can also make use of that for the department column. There I make use of type lookup.
Just select the corresponding List and the corresponding column of that list.
The laptop column is also of type choice with these three choices; Windows, macOS or None.
When the SP List is created, we can create a form so HR can easily fill in the new user’s information. For that, just hit the Forms option on the SP List page.
Click on New form.
A form is created, which we can change further to our needs.
If you want to store the department information in a SharePoint List, create the forms like this:
Department
Department Group Name
Department Group Object ID
Note; in both SP Lists I hide the default Title column to keep it as clear is possible later in the flow which column contains which data.
Setting up the flow
When we have our requirements in place including the SharePoint Lists, we can start building the Azure Logic Apps flow.
Sign in to the Azure portal and open the Logic App service. Create a Logic App of type Consumption.
We need to select a subscription, resource group, and region, and enter the name of the flow before we can create the Logic Apps flow.
When the flow is created, click on the name of the flow at the top of the screen, and open the Identity section. On the System assigned tab, set the switch to On.
Make sure to assign the application permissions to the system-assigned manager identity.
Browse to the Overview tab and click on Edit.
The first thing we need to add to the flow is a Trigger. Click on Add a trigger and search for When an item is created. In the list, you’ll find that trigger under SharePoint.
First sign in with your service account that has access to the SP List.
Next, select the Site Address where the SP List is located and select the List Name.
In case nothing is shown in the list, click on Enter custom value and paste the needed information.
Click on How often do you want to check for items. Here we select how often the flow checks for new items. It is up to you to configure this to your needs.
After the trigger, we add our first action. We add a Compose action, which is a Data Operations type action.
This compose action is an optional action. I use the action to convert the first and last name to lowercase characters. Just because I want the e-mail address to be set in lowercase 🙂
We can convert the characters with the expression ToLower. To add an expression to the action, hit the fx button.
In the pop up enter ToLower()
Set the cursor between the () signs and open the Dynamic content tab. On the dynamic content tab, we can search for variables (data) retrieved by previous actions and triggers. In this case, we search for first name. This is a value of the SharePoint trigger.
The expression should now look like below.
Click Add.
If we repeat these steps for last name as well and we enter a point in between the expressions, the output of this action would be firstname.lastname. We can use this as mail nickname later in the flow.
If you need another naming convention for the mail nickname, the above needs to be changed to your needs.
Next, we add an Initialize variable to the flow. We use this later to store the assigned licenses to the variable and send that in an e-mail to the user’s manager.
Enter a Name and select type String.
The next action will be an HTTP action. With this action, we will create the user account via a Graph API call.
Select POST as Method.
Next, select Authentication under Advanced parameters.
As Authentication type select Managed identity.
Select System-assigned managed identity from the list.
And add https://graph.microsoft.com as Audience.
Enter below URI:
https://graph.microsoft.com/v1.0/users
In the body field of the action, we need to fill in all the values we want to configure for the new user. I kept it pretty basic, so change it to your own needs.
I use the below JSON formatted body. You can copy that to the body field.
{
"accountEnabled": false,
"displayName": "",
"givenName": "",
"surname": "",
"otherMails": [
""
],
"mailNickname": "",
"userPrincipalName": "@",
"employeeHireDate": "T09:00:00Z",
"jobTitle": "",
"department": "",
"usageLocation": "",
"passwordProfile": {
"forceChangePasswordNextSignIn": false,
"password": ""
}
}
We can use the values from the SharePoint trigger, found as dynamic content by selecting the lighting button, to fill in all the values. Most are from the SharePoint trigger. The mailnickname and UserPrincipalName are from the Compose action.
I use the below expression to configure a random password of 17 characters and don’t send this to anybody. As on the hire date, I create a Temporary Access Pass to onboard the user.
Add this expression in the Body field for password.
The expression creates two guids of 8 characters, with an ! in between. The first guid contains uppercase characters and the second guid contains lowercase characters.
Expression;
concat(toUpper(substring(guid(),0,8)),'!',substring(guid(),0,8))
On the Settings tab of the HTTP action, under Security, we set the switch Secure inputs to On.
This makes sure the inputs field of the action is secured as that contains the generated password.
Next, we need to add a Parse JSON action, which is a Data operations action. We parse the output of the HTTP action, to be able to use the values later on in the flow.
Add the Parse JSON action to the flow.
In the Content field, we add Body, which is found as dynamic content of the HTTP action.
We don’t have to write the schema ourselves, we can generate it by adding a sample payload. We can get this example payload, by running the current flow and grabbing the output from the HTTP action. We can also grab the body when we run the same query via Graph Explorer.
This is my schema;
{
"type": "object",
"properties": {
"@@odata.context": {
"type": "string"
},
"id": {
"type": "string"
},
"businessPhones": {
"type": "array"
},
"displayName": {
"type": "string"
},
"givenName": {
"type": "string"
},
"jobTitle": {
"type": "string"
},
"mail": {},
"mobilePhone": {},
"officeLocation": {},
"preferredLanguage": {},
"surname": {
"type": "string"
},
"userPrincipalName": {
"type": "string"
}
}
}
And the Parse JSON action;
With the second HTTP action in the flow, we assign the manager to the new user account. Set Method to PUT.
As URI we use;
https://graph.microsoft.com/v1.0/users/[Body UserPrincipalName]/manager/$ref
Replace [Body UserPrincipalName] with the user principal name found via dynamic content of the Parse JSON action.
Use the below body:
{
"@@odata.id": "https://graph.microsoft.com/v1.0/users/[Manager Email]"
}
Replace [Manager Email] with the Manager email dynamic content of the SharePoint trigger.
Don’t forget to fill in the authentication information.
The next thing we will do is send an e-mail to the department which should prepare a laptop for the new user to inform them about this task. I use e-mail to inform them, but this could also be something else like a Teams message.
As it could also be possible that the new user doesn’t get a new piece of hardware, maybe only a Windows 365 machine will be offered, we first filter those out.
We use a Condition action for this filtering, which is a Control action.
As condition, we use Laptop Value is not equal to None. In my case, the three options for laptop are Windows, macOS, or None. Thus when the value is not equal to None we should send an email.
When the condition is true, we want to send an e-mail therefor we add a Send an email from a shared mailbox action to the flow under True.
We can fill in the information we need in the e-mail. As you can see we can also add information from previous actions to the e-mail. For example the hire date so the IT department knows before which date the laptop needs to be prepared.
The next step we take is assigning licenses via Entra ID group membership. Thus licenses are assigned to Entra ID groups in this environment.
If only a handful of licenses are available for assignment during user creation, we can use the column type choice in the SP List, to store those license types. And split up the flow for every license with a switch action.
The switch is made on the Microsoft license value. As soon as this dynamic content is added, the action is added to a For each loop.
We create a Case per license. And add the license information in the Equals field per case.
Under every case, we add an HTTP action that runs a POST call.
With the action,n we add the user to an Entra ID group.
The used URI is;
https://graph.microsoft.com/v1.0/groups/[Group Object ID]/members/$ref
Replace [Group Object ID] with the object ID of the related group to which the related license is assigned.
As Body we use;
{
"@@odata.id": "https://graph.microsoft.com/v1.0/directoryObjects/[Body id]"
}
Replace [Body id] with the dynamic content Body id of the Parse JSON action.
In every case, under the HTTP action, we add an Append to string action.
In this action, we store information about which license is assigned. We use this information later in the flow.
This is what the switch and cases look like.
Note; to make our lives easier when building the above switch and cases, we can right-click the HTTP and Variable action, to copy these and past them in the next case, This way, we only need to change a part of the action instead of repeatedly creating the same actions.
Now we’re going to collect the information on all the licenses that are assigned with another Compose action.
Add the varLicense to the Inputs field, found via dynamic content.
The next step is to assign the department Entra ID group. For this we could have taken the same approach as with assigning the license, but let’s use another approach for this one. This is an approach that might be easier to maintain, certainly when more than a handful of options are available. But it also means an additional SP list.
For this to work, we first retrieve the items of the Department SharePoint List with a Get items action.
Select the Site Address and List Name.
As we only want to retrieve the information of the SP List items that match the department to which the user needs to get assigned, we make use of a Filter Query;
Department eq ‘Department value’.
In this, the Department value is dynamic content of the SP trigger.
We use an HTTP POST action again to assign group membership. We don’t need all the cases under a switch this time, like we used for the license group membership. Just the SP List, Get items action, and the HTTP action.
The URI for this call is;
https://graph.microsoft.com/v1.0/groups/[DepartmentGroupObjectID]/members/$ref
Replace [DepartmentGroupObjectID] with the value from the latest Get items action. It should correspond with the Group object id column of the SP List.
As Body we use:
{
"@@odata.id": "https://graph.microsoft.com/v1.0/directoryObjects/[Body id]"
}
Replace [Body id] with the Body id value of the Parse JSON action. This ID is from the created user account.
The flow will be ended with sending out two e-mails.
We send an e-mail to HR, like the below example.
To send out an e-mail at the same time, we can add a parallel branch to the flow. And in that parallel branch, we can add the email action for the manager.
The e-mail to inform the manager.
To add some error handling in case an action fails, I added another send an e-mail action.
Add this action below one of the two latest send e-mail actions.
On the Settings tab of this send an email action, scroll to the Run after section. First, make sure both the latest e-mail actions are added via Select actions. Then for both actions select Has timed out, Is skipped, and Has failed. And unselect Is successful. This makes sure the e-mail is sent when an error happens with one of the actions.
This is how that should look now.
As last we add a Terminate action to the flow to terminate the action and mark it as failed when an error occurs.
This is the flow we created for our user creation.
The end result
Our HR department can fill in the new user’s information via Microsoft Forms.
When the automation flow is finished, the user account is created in Entra ID.
The user principal name is set, same is for mail nick name (in lower case).
Besides that we see the job title and department are configured and the manager is assigned. Also the usage location is set.
We can see the user is a member of license and department groups.
And because of the license group membership, the license is assigned to the user.
The end result is that we can build a low-cost automation solution for the creation of user accounts in Entra ID. By filling in the form we trigger the flow and in a couple of seconds the user account is created.
The JSON template to deploy the flow can be found on GitHub including a script to assign permissions to the Managed Identity.
Hit the below button to directly upload the template to your Azure environment.

Thanks for reading. Also have a look at the follow-up blog post Build your own user onboarding automation – Day 1: enable the account and create a Temporary Access Pass.
Keep an eye on my blog and socials as the onboarding automation series will expand with additional blog posts!
6 Comments
Very good Peter. I have used PowerApps as the frontend form, its more dynamic but needs more coding on the frontend. Your post is simple and flat on the front end which is very useful in some use cases where I felt PowerApps is a bit of an overkill. Your form can also be connected to the Generic HR App connector which can provision to on-prem AD. I am looking forward to when forms will be added to Logic apps. What I want to do is custom group management (Entra and AD)
Hi Ike,
You can create a form that just creates an item in the SharePoint List, like I show in this post; https://inthecloud247.com/build-your-own-user-onboarding-automation-entra-id-user-account-creation/
It might also do the job for you.
Thanks for the excellent article, Peter! Would this type of flow be able to automatically provision an Entra ID user that has recently been created and synced from AD?
Hi Jonathan,
With the API-driven provisioning to on-premises Active Directory solution of Microsoft you’re able to manage user accounts in the on-premises AD. I wrote an article on disabling the AD account with that solution, but it could also create accounts in the AD; https://inthecloud247.com/revoke-user-access-in-case-of-an-emergency-with-a-single-click-on-premises-ad-integration/
Hey Peter,
So the AD user creation is something we are looking to handle through separate integration. What I’m wondering is if the logic app flows for Entra ID can be used to simply detect a newly created user and then provision its licensing, o365 group memberships, etc.
Hope that makes sense. 🙂
With some filtering like in this post https://inthecloud247.com/build-your-own-user-onboarding-automation-day-1-enable-the-account-and-create-a-temporary-access-pass/ it is possible to check on the creation or hire date for example of newly created users.