Recently I shared this blog post about creating a low-code automation solution to easily create users in Entra ID. This is the follow-up blog post in the user onboarding automation series.
This second automation flow enables the user account of users that have a hire date of today. Besides that a Temporary Access Pass is created for passwordless onboarding. The new user is informed on the personal e-mail account and the manager is informed a new colleague is starting today.
The solution is short
This second Logic Apps flow runs every day, early in the morning, and checks for all user accounts in the Entra ID environment of which the status is disabled and the creation date is in the last 7 days. The idea of this is that the automatically created accounts are still in a disabled state and have been created in the past week. When the hire date of one of these accounts matches the date of today, the flow is further executed. The flow creates a Temporary Access Pass (TAP) for the user, with the start date/ time today 9:00AM and lifetime for 180 minutes. This means the onboarding can be done with the TAP between 9:00AM and 12:00PM.
The users manager is retrieved, to inform the manager per e-mail about the new joiner and the TAP is shared with the manager. Also the new user is informed by the flow on the personal email address, sharing some welcome information including the User Principal Name.
The flow is available as a template on my GitHub repo for easy deployment.
Requirements
We have some requirements that need to be in place before we can use our Logic Apps flow.
To enable the user account, create a TAP and get the managers information, we make use of Graph API queries. To be allowed to run these queries, we need an identity for authentication and to assign permissions to. I prefer to make use of a Managed Identity, as that is an easy to manage and secure option. 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) permissions to execute all the Graph calls we make. These are the application permissions needed for our flow;
User.ReadWrite.All
UserAuthenticationMethod.ReadWrite.All
As I inform the manager and new user per e-mail, I need a (service) account to send e-mails from a shared mailbox. If you have other needs to inform the manager or user, this requirement differs.
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 Apps 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 Schedule. We need to add a Recurrence trigger to the flow.
With the recurrence trigger, we trigger the flow to start based on the schedule we create. I want to run the flow every day, at 6:00AM and to avoid issues with time zones, I also select the Time Zone.
Next, we add our first HTTP action to run a Graph API call.
With this HTTP action we query all Entra ID user accounts, that are disabled. Besides that the filter checks if it is created in the last 7 days and the hire date is before tomorrow 00:00. This way it doesn’t matter if the time in the hire date is 9:00AM or 9:00PM for example.
Select GET 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?$select=id,displayName,givenName,surname,userPrincipalName,mail,otherMails,accountEnabled,createdDateTime,employeeHireDate&$filter=employeeHireDate%20le%20@{formatDateTime(addDays(utcNow(),1),'yyyy-MM-dd')}T00:00:00Z%20and%20createdDateTime%20ge%20@{formatDateTime(addDays(utcNow(),-7),'yyyy-MM-dd')}T00:00:00Z%20and%20accountEnabled%20eq%20false&$count=true
In the above URI we have something with [formatDateTime] twice. These are Expressions. With these expressions we can add the current date and time, but also add hours or days to the current date/ time. Or we can take the current date minus a number of days. We can add expressions by clicking on the fx button.
For the hire date I want to use the date of tomorrow and time 00:00, so I know the hire date of today, no matter which time is set, will be returned by the filter. Therefor we can use the below expression, which adds a day to uctNow (which means today, this time). And I also specify the format, which is yyyy-MM-dd. With this format I only retrieve the date, and not the time. As the time is specified already in the URI.
formatDateTime(addDays(utcNow(),1),'yyyy-MM-dd')
For the created Date, I want the current date, minus 7 days. In case you create the accounts even more days, before the start date, change this expression to your needs.
formatDateTime(addDays(utcNow(),-7),'yyyy-MM-dd')
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. Dynamic content can be found by hitting the lightning button.
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.
Schema:
{
"type": "object",
"properties": {
"@@odata.context": {
"type": "string"
},
"@@odata.count": {
"type": "integer"
},
"value": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"displayName": {
"type": "string"
},
"givenName": {
"type": "string"
},
"surname": {
"type": "string"
},
"userPrincipalName": {
"type": "string"
},
"mail": {
"type": "string"
},
"otherMails": {
"type": "array",
"items": {
"type": "string"
}
},
"accountEnabled": {
"type": "boolean"
},
"createdDateTime": {
"type": "string"
},
"employeeHireDate": {
"type": "string"
}
},
"required": [
"id",
"displayName",
"givenName",
"surname",
"userPrincipalName",
"mail",
"otherMails",
"accountEnabled",
"createdDateTime",
"employeeHireDate"
]
}
}
}
}
And the Parse JSON action;
For some error handling I added a Condition action, which is a Control action, to the flow. With this condition I check if the employee hire date starts with the day of today. Just to make sure we don’t run the flow for an user who will start tomorrow, for example.
In the left field, we add employeeHireDate which is a value from the Parse JSON action. This adds the Condition action in a For each action. This is a loop action, to loop through all disabled accounts.
Select starts with from the drop-down list.
In the right field add below expression, to add the current date to the condition:
formatDateTime(utcNow(),'yyyy-MM-dd')
And this is our condition action. When the hire date starts with the date of today, the outcome is true and the flow continues.
Under True, we add an HTTP action.
Select PATCH 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/[ID]
Replace [ID] with the ID found as dynamic content from the Parse JSON action.
As body we use below JSON to enable the user account:
{
"accountEnabled": true
}
In the next HTTP action, we will create the Temporary Access Pass.
Select POST as Method.
With this URI:
https://graph.microsoft.com/v1.0/users/[ID]/authentication/temporaryAccessPassMethods
Replace [ID] with the ID found as dynamic content from the Parse JSON action.
And the below JSON in the Body field:
{
"startDateTime": "[formateDateTime]T09:00:00.000Z",
"lifetimeInMinutes": 180,
"isUsableOnce": false
}
Fill in the required header information:
Content-Type – application/json
As date we use an expression, to replace [formateDateTime]:
formatDateTime(utcNow(),'yyyy-MM-dd')
This will set the start date time for the TAP to today with a start time of 9:00.
Change the time, lifetime and is usable once to your own needs.
The TAP is readable in the history of the flow. This means everybody with access to the flow has access to the TAP. To avoid this, we can change the security of the HTTP Action on the Settings tab.
Under security, switch Secure inputs/ outputs to On.
We need to parse the output from the HTTP action with a Parse JSON action.
Add the Body from the HTTP action in the Content field and create the schema.
Schema:
{
"type": "object",
"properties": {
"@@odata.context": {
"type": "string"
},
"id": {
"type": "string"
},
"isUsable": {
"type": "boolean"
},
"methodUsabilityReason": {
"type": "string"
},
"temporaryAccessPass": {
"type": "string"
},
"createdDateTime": {
"type": "string"
},
"startDateTime": {
"type": "string"
},
"lifetimeInMinutes": {
"type": "integer"
},
"isUsableOnce": {
"type": "boolean"
}
}
}
To be able to inform the manager of the new user, we need to get some information of the manager. This can be retrieved with a HTTP Get action.
We use the below URI:
https://graph.microsoft.com/v1.0/users/[ID]/manager?$select=id,displayName,givenName,surname,mail
Replace [ID] with the ID found as dynamic content from the first Parse JSON action.
And of course, this is followed by a Parse JSON action:
The account is enabled, the Temporary Access Pass created and information about the manager retrieved. We can now inform the manager and the new colleague.
Add a Send and email from a shared mailbox action.
Fill in an Original Mailbox Address from the shared mailbox. In the To field, we can add mail. This is a dynamic content value of the Parse JSON action related to the HTTP action that retrieved the managers information.
Add some text to your needs to the Body field. In the body we also include the Temporary Access Pass.
On the settings tab, under Security switch on Secure inputs/ outputs (as the action contains the TAP).
We add a parallel branch to the flow, to run both send email actions at the same time. For this, hit the plus button above the first send an email action and select Add a parallel branch. Under the new branch, add the second Send an email action.
Fill in the information to your needs, including the User Principal Name of the new user. The UPN is dynamic content from the Get disabled users Parse JSON action.
In the To field, we need to enter the new colleagues personal e-mail, which is stored under otherMails (at least I hope it is, otherwise you don’t have an option to share the UPN automatically with the new colleague).
OtherMails could contain multiple e-mail addresses, therefor we use below expression to grab the first mail address:
first(item()?['otherMails'])
With the send an email action added, we finished our flow.
At the end of the flow, we can add some actions for error handling like shown in the first part of this onboarding series.
The end result
The end-result is that the users account is enabled on the hire date and a Temporary Access Pass is created.
The users manager is informed the new colleague starts today and the TAP is shared with the manager.
The new colleague itself is also informed by e-mail. In the e-mail the user can find the User Principal Name and inform the user this is shared with the manager.
By creating the two Azure Logic Apps flows we created low-code automation for our HR department, so they can easily create new user accounts, including license and group assignment. Early in the morning of the hire date, the users account is enabled, a TAP created and both the manager and user are informed.
That’s it for now. Keep an eye on the upcoming blog posts related to automating the user onboarding experience.
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 upload the template to your Azure environment directly.

Thanks for reading!